intl-validation
v0.2.4
Published
validation messages for constraint validation
Maintainers
Readme
Internationalization of HTML validation
intl-validation validates input-like objects against common HTML constraint-validation rules and resolves localized validation messages in over 50 languages.
Installation
npm install intl-validationvalidate()
validate(input, language?, library?) returns a [flags, message] tuple:
inputaccepts the same constraint-related properties as an<input>element.languageis an optional BCP 47 locale string. It defaults to"en".libraryis an optional dictionary map keyed by language code.
The flags object follows the DOM ValidityState shape, and the message is the resolved localized string. When the input is valid, the result is [{ }, ""].
import { validate } from "intl-validation";
validate({ value: "test" });
// [{}, ""]
validate({ value: "", required: true });
// [{ valueMissing: true }, "Fill out this field"]
validate({ type: "email", value: "" });
// [{}, ""]
validate({ type: "email", value: "not-an-email" });
// [{ typeMismatch: true }, "Enter an email address"]
validate({ value: "abcdef", maxLength: 5 });
// [{ tooLong: true }, "Use no more than 5 characters"]Selecting a language
The package does not read navigator.language; pick a locale explicitly.
The default bundled library only includes English, so to resolve another language you should provide a library containing that locale (and typically English as a fallback):
import en from "intl-validation/messages/en.js";
import es from "intl-validation/messages/es.js";
import { validate } from "intl-validation";
const [flags, message] = validate(
{ required: true, value: "" },
"es",
{ en, es },
);
// flags.valueMissing === true
// message === "Completa este campo"Language selection works in this order:
- exact locale match, such as
"pt-BR" - base language match, such as
"pt" - English fallback,
"en"
Message resolution
Many keys come in qualified variants — valueMissing.checkbox for type="checkbox", tooLong.one for singular counts, and additional plural categories such as .few or .many where available. validate() picks the most specific variant in this order:
- Type-qualified —
valueMissing.checkbox,typeMismatch.email,badInput.number, … - Plural-qualified —
tooLong.one,tooShort.few, … (selected viaIntl.PluralRulesfor the chosen language) - Bare key —
tooLong,valueMissing, …
Numeric limits (minLength, maxLength, min, max) replace the @ placeholder in the resolved message.
test()
When you only need the failed constraint name — for example, to drive your own UI or custom message formatter — use test from the subpath export:
import { test } from "intl-validation/test.js";
test({ value: "test" });
// ""
test({ value: "", required: true });
// "valueMissing"
test({ type: "email", value: "not-an-email" });
// "typeMismatch"
test({ value: "abcdef", maxLength: 5 });
// "tooLong"test() runs the same constraint checks as validate(), but returns only the first failed validity flag and skips message lookup.
Loading dictionaries directly
Each locale is available as both a JavaScript module and a JSON file:
import messages from "intl-validation/messages/en.js";
console.log(messages["valueMissing"]); // "Fill out this field"
console.log(messages["typeMismatch.email"]); // "Enter an email address"import messages from "intl-validation/messages/en.json" with { type: "json" };
console.log(messages["valueMissing"]); // "Fill out this field"
console.log(messages["typeMismatch.email"]); // "Enter an email address"Lazy-loading dictionaries
The package also ships lazy loaders for three locale sets:
intl-validation/messages/loaders/core.jsintl-validation/messages/loaders/extended.jsintl-validation/messages/loaders/complete.js
Each loader module exports a default object whose values are async functions resolving directly to locale dictionaries:
import en from "intl-validation/messages/en.js";
import loaders from "intl-validation/messages/loaders/complete.js";
import { validate } from "intl-validation";
const es = await loaders.es();
const [flags, message] = validate({ required: true, value: "" }, "es", { en, es });Available Messages
Each language ships as both a JavaScript module (messages/<language-code>.js) and an equivalent JSON file (messages/<language-code>.json). Both contain the same key/value pairs:
| Key | Description | English Sample |
|:--- |:----------- | ------------:|
| badInput.number | Invalid number input | "Enter a number" |
| patternMismatch | Pattern constraint violation | "Match the requested format" |
| rangeOverflow | Value above maximum | "Value must be less than or equal to @" |
| rangeUnderflow | Value below minimum | "Value must be greater than or equal to @" |
| tooLong | Value too long | "Use no more than @ characters" |
| tooShort | Value too short | "Use at least @ characters" |
| stepMismatch | Step constraint violation | "Enter a valid value" |
| typeMismatch | Generic type mismatch | "Invalid value" |
| typeMismatch.email | Invalid email format | "Enter an email address" |
| typeMismatch.url | Invalid URL format | "Enter a URL" |
| valueMissing | Generic required field | "Fill out this field" |
| valueMissing.checkbox | Required checkbox | "Select this checkbox" |
| valueMissing.file | Required file input | "Select a file" |
| valueMissing.radio | Required radio button | "Select one of these options" |
| valueMissing.select | Required select/dropdown | "Select an item in the list" |
| valueMissing.switch | Required switch/toggle | "Tap this switch" |
Supported Languages
53 distinct languages are available:
| Code | Language | Loader set | |------|----------|------------| | ar | Arabic | Core | | as | Assamese | Complete | | bg | Bulgarian | Extended | | ca | Catalan | Extended | | cs | Czech | Core | | da | Danish | Core | | de | German | Core | | el | Greek | Core | | en | English | Core | | eo | Esperanto | Complete | | es | Spanish | Core | | et | Estonian | Extended | | eu | Basque | Complete | | fa | Persian | Core | | fi | Finnish | Core | | fr | French | Core | | gl | Galician | Extended | | gu | Gujarati | Extended | | he | Hebrew | Core | | hi | Hindi | Core | | hr | Croatian | Extended | | hu | Hungarian | Core | | id | Indonesian | Core | | it | Italian | Core | | ja | Japanese | Core | | ka | Georgian | Extended | | kn | Kannada | Extended | | ko | Korean | Core | | lt | Lithuanian | Extended | | lv | Latvian | Extended | | ml | Malayalam | Extended | | mr | Marathi | Extended | | nb | Norwegian Bokmål | Extended | | nl | Dutch | Core | | or | Odia | Extended | | pa | Punjabi | Extended | | pl | Polish | Core | | pt | Portuguese | Core | | pt-BR | Portuguese (Brazil) | Core | | ro | Romanian | Core | | ru | Russian | Core | | sl | Slovenian | Extended | | sr | Serbian | Extended | | sr-Latn | Serbian (Latin) | Extended | | sv | Swedish | Core | | ta | Tamil | Extended | | te | Telugu | Extended | | th | Thai | Core | | tr | Turkish | Core | | uk | Ukrainian | Core | | vi | Vietnamese | Core | | zh | Chinese | Core | | zh-TW | Chinese (Traditional) | Core |
Local Development
To regenerate the translation files:
npm run buildThis runs a Python script that fetches the latest translations from WebKit's repository and emits both lib/messages/<lang>.js and lib/messages/<lang>.json for each supported language.
