Two Ways To Create Custom Translated Messaging For HTML Forms


HTML forms come with built-in ways to validate form inputs and other controls against predefined rules such as making an input required, setting min and max constraints on range sliders, or establishing a pattern on an email input to check for proper formatting. Native HTML and browsers give us a lot of “free” features that don’t require fancy scripts to validate form submissions.

And if something doesn’t properly validate? We get “free” error messaging to display to the person using the form.

These are usually good enough to get the job done, but we may need to override these messages if we need more specific error content — especially if we need to handle translated content across browsers. Here’s how that works.

The Constraints API

The Constraints API is used to override the default HTML form validation messages and allows us to define our own error messages. Chris Ferdinandi even covered it here on CSS-Tricks in great detail.

In short, the Constraints API is designed to provide control over input elements. The API can be called at individual input elements or directly from the form element.

For example, let’s say this simple form input is what we’re working with:

We can set our own error message by grabbing the element and calling the setCustomValidity() method on it before passing it a custom message:

const fullNameInput = document.getElementById("fullName");
fullNameInput.setCustomValidity("This is a custom error message");

When the submit button is clicked, the specified message will show up in place of the default one.

A form field labeled "Full Name" with an input box to enter the name, a "Submit" button, and a displayed custom error message: "This is a custom error message" with a warning icon.

Translating custom form validation messages

One major use case for customizing error messages is to better handle internationalization. There are two main ways we can approach this. There are other ways to accomplish this, but what I’m covering here is what I believe to be the most straightforward of the bunch.

Method 1: Leverage the browser’s language setting

The first method is using the browser language setting. We can get the language setting from the browser and then check whether or not we support that language. If we support the language, then we can return the translated message. And if we do not support that specific language, we provide a fallback response.

Continuing with the HTML from before, we’ll create a translation object to hold your preferred languages (within the script tags). In this case, the object supports English, Swahili, and Arabic.

const translations = {
  en: {
    required: "Please fill this",
    email: "Please enter a valid email address",
 
  },
  sw: {
    required: "Sehemu hii inahitajika",
    email: "Tafadhali ingiza anwani sahihi ya barua pepe",
  },
  ar: {
    required: "هذه الخانة مطلوبه",
    email: "يرجى إدخال عنوان بريد إلكتروني صالح",
  }
};

Next, we need to extract the object’s labels and match them against the browser’s language.

// the translations object
const supportedLangs = Object.keys(translations);
const getUserLang = () => {
  // split to get the first part, browser is usually en-US
  const browserLang = navigator.language.split('-')[0];
  return supportedLangs.includes(browserLang) ? browserLang :'en';
};

// translated error messages
const errorMsgs = translations[getUserLang()];// form element
const form = document.getElementById("myForm");// button elementconst btn = document.getElementById("btn");// name input
const fullNameInput = document.getElementById("fullName");// wrapper for error messaging
const errorSpan = document.getElementById("error-span");

// when the button is clicked…
btn.addEventListener("click", function (event) {  // if the name input is not there…
  if (!fullNameInput.value) {    // …throw an error
    fullNameInput.setCustomValidity(errorMsgs.required);    // set an .error class on the input for styling
    fullNameInput.classList.add("error");
  }
});

Here the getUserLang() function does the comparison and returns the supported browser language or a fallback in English. Run the example and the custom error message should display when the button is clicked.

A form field labeled "Full Name" with a placeholder text "Enter your full name" is outlined in red with an error message saying "Please fill this" below it. There is also a "Submit" button next to the field.

Method 2: Setting a preferred language in local storage

A second way to go about this is with user-defined language settings in localStorage. In other words, we ask the person to first select their preferred language from a      

With the element const languageSelect = document.getElementById("languageSelect"); // the

element const form = document.getElementById("myForm"); // the button element const btn = document.getElementById("btn"); // the name input const fullNameInput = document.getElementById("fullName"); const errorSpan = document.getElementById("error-span"); // translated custom messages const translations = {   en: {     required: "Please fill this",     email: "Please enter a valid email address",   },   sw: {     required: "Sehemu hii inahitajika",     email: "Tafadhali ingiza anwani sahihi ya barua pepe",   },   ar: {     required: "هذه الخانة مطلوبه",     email: "يرجى إدخال عنوان بريد إلكتروني صالح",   } }; // the supported translations object const supportedLangs = Object.keys(translations); // get the language preferences from localStorage const getUserLang = () => {   const savedLang = localStorage.getItem("preferredLanguage");   if (savedLang) return savedLang;   // provide a fallback message   const browserLang = navigator.language.split('-')[0];   return supportedLangs.includes(browserLang) ? browserLang : 'en'; }; // set initial language languageSelect.value = getUserLang(); // update local storage when user selects a new language languageSelect.addEventListener("change", () => {   localStorage.setItem("preferredLanguage", languageSelect.value); }); // on button click btn.addEventListener("click", function (event) {   // take the translations   const errorMsgs = translations[languageSelect.value];   // ...and if there is no value in the name input   if (!fullNameInput.value) {     // ...trigger the translated custom validation message     fullNameInput.setCustomValidity(errorMsgs.required);     // set an .error class on the input for styling     fullNameInput.classList.add("error");   } });

The script sets the initial value to the currently selected option, saves that value to localStorage, and then retrieves it from localStorage as needed. Meanwhile, the script updates the selected option on every change event fired by the