Arabic form validation messages
Write and display Arabic form errors, replace browser-generated English messages, and test corrections, server responses and accessible feedback.
By Omran Khleifat, Founder of Ritla
Guide13 min read
An Arabic form can look fully translated until someone submits it empty. The browser opens an English validation bubble, a server response inserts an English sentence, or an error appears below a field without explaining what to change. Reviewing the form before submission misses all three.
Arabic form validation messages need their own implementation and test states. Translating the label does not translate the browser's interface. Setting right-to-left direction does not translate an API response. An untranslated error leaves the person with a blocked task and no usable correction, the problem described by : Untranslated form labels / validation / help text.
This guide uses a community garden application. Applicants describe their planting plan and choose a plot. The examples distinguish a missing description, a plot that has become unavailable and a request that could not reach the service. Those failures need different instructions, even when they interrupt the same submit action.
Why an Arabic page still shows an English error#
Start with a required field and an Arabic submit button:
<form id="garden-request" lang="ar" dir="rtl" method="post"> <label for="planting-plan">خطة الزراعة</label> <input id="planting-plan" name="plantingPlan" required> <button type="submit">إرسال الطلب</button></form>Submitting the empty field invokes the browser's constraint validation. The browser supplies its own message unless the application supplies a custom one. That message is outside your translation catalog.
In the supplied browser measurements, Chromium 151 on September 24, 2026 showed its English required-field message on a page with lang="ar". Firefox and Safari were not measured. The useful conclusion is that the page language does not guarantee Arabic browser-generated validation. Test the browser and operating-system combinations you support instead of assuming one language-selection rule covers them all.
Keep the Arabic language declaration. It still describes the content. Keep dir="rtl" for the Arabic interface too. Neither attribute is an instruction to translate browser chrome. Their separate responsibilities are explained in lang="ar" versus dir="rtl".
A translated title or placeholder is not a replacement for a controlled validation message. Nor should users have to change their browser language to finish an Arabic application. Decide whether your product accepts browser-owned messages or promises Arabic feedback regardless of browser language, then implement that decision deliberately.
Identify who owns each message#
Before editing a translation file, reproduce the failure and identify its source. The same field can receive feedback from several layers.
| Source | Garden application example | Where the Arabic wording belongs |
|---|---|---|
| Native constraint validation | The planting plan is empty | Custom validity text or application-owned feedback |
| Client application rules | The description contains only spaces | A translated message keyed to that rule |
| Server field validation | The selected plot is no longer available | A localized mapping from a stable server error code |
| Request failure | The application could not contact the service | A form-level message with a suitable next action |
Inspect the DOM while the error is visible. An inline paragraph or toast belongs to the application; a native validation bubble does not become a DOM paragraph that your translation library can replace. Inspect the response payload separately from what the interface displays.
This distinction changes the fix. A missing catalog entry needs translation. A raw backend sentence needs a response-to-message mapping. A browser bubble needs a decision about native validation. Repeatedly searching the frontend catalog for an English string cannot fix a sentence that only the browser generates.
Record the triggering condition with the message, not just a screenshot. “Submit with no planting plan” reproduces a missing-value branch. “Choose a plot, have it become unavailable, then submit” reproduces a server branch. Without that distinction, a tester can confirm one Arabic error while another remains English.
Write the correction the applicant can perform#
An error should identify the problem and give the next action when that action is known. W3C's Error Suggestion guidance makes that distinction explicit: detecting an error is different from explaining its correction.
For an empty planting plan, compare these messages:
Unhelpful: حدث خطأ.Actionable: اكتب خطة الزراعة قبل إرسال الطلب.The second message says which task remains unfinished. It does not blame the applicant or suggest the whole service is broken.
For a plot that someone else has taken, the correction changes:
لم تعد القطعة المختارة متاحة. اختر قطعة أخرى.Do not reuse the missing-value instruction here. The person already selected a plot. Asking them to select one without explaining the changed availability makes the interface appear to have ignored their work.
For a connection failure, an instruction to edit the planting plan would be false. Use a form-level message explaining that sending failed and offering a retry if that matches the actual request state. If the outcome is uncertain, reconcile it with the server before encouraging another submission that could create a duplicate.
Keep labels, help and errors consistent. If the visible label calls the field a planting plan, the error should not introduce “project narrative” as a second name. Give translators the label, the validation condition, the allowed values and the intended action together. A key such as invalid gives them none of that context.
Have an Arabic reviewer evaluate the complete interaction, including the correction. A sentence can be grammatically sound while naming a nonexistent button or asking for a format the field refuses to accept.
Make the message agree with the validation rule#
Translation cannot repair a rule that rejects the intended answer. If the garden's planting-plan field accepts natural Arabic descriptions, an ASCII-only letters rule is a validation defect. Replacing its English rejection with an Arabic sentence would make the defect readable while leaving the applicant unable to proceed.
Write down the acceptance rule beside each message. For a description length limit, specify what the implementation counts, whether surrounding whitespace counts and whether the server uses the same measure. Native minlength measures UTF-16 code units, which are not necessarily the visible characters a person counts. Combining marks and supplementary characters make a vague instruction to add “characters” harder to interpret.
If the product promises a visible-character limit, implement that agreed measure consistently in the counter and validators. Do not show a counter based on one unit while rejecting the answer with another. If native length validation remains part of the design, include its user-editing behavior in the test plan: a script assigning a value is not an equivalent fixture for every native length constraint.
For several simultaneous failures, choose a correction order. A missing value should not produce a format example for content the applicant has not entered. After that correction, the next message can explain a remaining constraint. Test that sequence, because translating each message independently does not establish that the application selects the right one.
Do not wait for submit to translate a native failure#
This approach looks plausible:
const gardenForm = document.querySelector("#garden-request");const planField = document.querySelector("#planting-plan"); gardenForm.addEventListener("submit", () => { if (planField.validity.valueMissing) { planField.setCustomValidity("اكتب خطة الزراعة قبل إرسال الطلب."); }});It arrives too late for the empty required field. Native validation can prevent submission before a submit event is dispatched. MDN documents this sequence in its submit event reference. The handler never gets the opportunity it was relying on.
For browser-owned presentation, prepare custom messages before interactive validation, refresh them when values change, and cover every applicable constraint. You can also handle the control's invalid event. If delegating that event from a form, use a capture listener because it does not bubble.
For application-owned presentation, suppress automatic interactive validation and run your own submit-time feedback path. Keep the field constraints where they express the real requirement. The HTML validity API remains useful without using its native bubble.
Do not remove required merely to make your submit listener run. That changes the form's declared requirements. Choose who presents the error instead of weakening the rule that produced it.
Also distinguish a validity read from a validation operation. Reading field.validity.valid inspects state. Calling checkValidity() also dispatches invalid when the control fails. A logging helper that calls it can therefore trigger application feedback while supposedly only inspecting a field.
Clear custom validity before deciding whether it is fixed#
setCustomValidity() changes validity, not just wording. A nonempty message makes the control invalid until that custom message is cleared. MDN's setCustomValidity reference documents this behavior.
For the required-only planting-plan field above, a native-message preparation function can be this small. Use this instead of the preceding submit listener:
const planInput = document.querySelector("#planting-plan"); function preparePlanMessage() { planInput.setCustomValidity(""); if (planInput.validity.valueMissing) { planInput.setCustomValidity("اكتب خطة الزراعة قبل إرسال الطلب."); }} preparePlanMessage();planInput.addEventListener("input", preparePlanMessage);The initial call handles an untouched empty field. The input listener clears the previous custom error and evaluates the current native condition. This example changes native message text; it does not create persistent inline feedback or add a whitespace-only rule.
The fragile version first asks whether validity.valid is false and then assigns a message. After the first failure, its own custom message keeps that condition false even after the applicant corrects the value. Clearing comes first.
Run the preparation function after application code restores or replaces the value too. Programmatic value assignment does not dispatch the typing-related input event. If another part of the application owns a server error for this control, coordinate that state explicitly: a function that blindly clears custom validity must not silently discard an unresolved server rejection.
When adding another constraint later, update the mapping. Otherwise the missing-value branch is Arabic while the newly introduced format or range branch falls back to browser-generated text.
Give persistent Arabic errors a complete presentation path#
For a product that promises consistent Arabic feedback, persistent inline messages give you control over wording, placement and correction state. They also remain available after the browser bubble would have disappeared.
Here is an alternative implementation of the same garden field. Replace the earlier markup and scripts with this pair. The containing route must accept the shown POST field and render its own Arabic server errors; these snippets implement client feedback, not that server handler.
<form id="garden-request" lang="ar" dir="rtl" method="post"> <label for="planting-plan">خطة الزراعة</label> <p id="plan-help">اذكر ما تنوي زراعته في القطعة.</p> <input id="planting-plan" name="plantingPlan" required aria-describedby="plan-help"> <p id="plan-error" hidden></p> <button type="submit">إرسال الطلب</button></form>const form = document.querySelector("#garden-request");const field = document.querySelector("#planting-plan");const error = document.querySelector("#plan-error");let attempted = false; function currentMessage() { return field.value.trim() === "" ? "اكتب خطة الزراعة قبل إرسال الطلب." : "";} function renderError(message) { error.textContent = message; error.hidden = message === ""; if (message) { field.setAttribute("aria-invalid", "true"); field.setAttribute("aria-describedby", "plan-help plan-error"); } else { field.removeAttribute("aria-invalid"); field.setAttribute("aria-describedby", "plan-help"); }} field.addEventListener("input", () => { if (attempted) renderError(currentMessage());}); form.addEventListener("submit", (event) => { attempted = true; const message = currentMessage(); renderError(message); if (message) { event.preventDefault(); field.focus(); }}); form.noValidate = true;This version treats whitespace-only content as missing, a stated application rule. It does not trim or rewrite the submitted description. Once JavaScript has installed the handlers, noValidate suppresses native interactive validation so the submit handler can present the Arabic error. Without JavaScript, the markup retains native required-field validation, whose message language still needs the earlier caveat. See MDN's constraint validation guide for that distinction.
The example deliberately validates one field. Adding more fields means adding their actual rules, associations and submit-time focus strategy. A blanket noValidate on a large existing form without that replacement leaves previously constrained fields without equivalent client feedback. Server validation remains necessary in either design.
Notice that help survives the error state. Replacing aria-describedby with only the error ID would drop the persistent instruction. Correcting the value removes the error association and invalid state together. MDN's aria-invalid guidance explains why an untouched empty required field should not immediately be announced as an error.
Use error codes as the translation boundary#
Do not translate server failures by comparing their English sentences. Backend punctuation, wording or library upgrades would then change frontend behavior.
For the plot availability failure, define a response contract such as:
{ "field": "plotId", "code": "plot_unavailable", "parameters": { "plotReference": "GDN-R6-284" }}The frontend maps the code to a complete Arabic message and a known field. The reference is data. The server's optional diagnostic sentence is not customer-facing copy.
Handle an unknown code deliberately. Present an Arabic fallback that says the request could not be completed, preserve the applicant's entries and offer an action supported by the actual failure. Record the unmapped code for investigation. Do not dump an English exception or a translation key into the form because the specific translation is missing.
Keep field and form errors separate. An unavailable plot belongs beside the plot choice. A service outage belongs at form level. If several fields participate in one rule, explain their relationship and link the correction to the relevant controls rather than attaching the same unexplained sentence everywhere.
Store the error code and parameters in state, then derive the visible sentence from the active locale. Storing only the rendered Arabic or English sentence makes language switching harder: labels update while existing errors remain in the previous language. Re-render summaries and inline feedback together when the locale changes.
Check shared component defaults as a separate source of English. A translated page can mount a form library whose validation messages still use its default locale. A later translation bundle can also arrive after the applicant has already triggered an error. Test that loading sequence on a fresh visit, rather than relying on a warm session with translations already cached.
Provide the Arabic message catalog before enabling the interaction that needs it, or define an Arabic loading and fallback path. A test that sees only the final translated screen can miss an English error shown earlier. Missing-key fallback should be an explicit product choice, with a usable Arabic sentence for unknown failures, rather than an accidental consequence of the library's English development defaults.
Translate complete messages and isolate inserted values#
Arabic grammar needs the whole sentence. Give translators one message with named parameters and context, rather than independently translating a field name, a failure adjective and a button caption and joining them at runtime.
Avoid repeating the rejected value when the correction does not need it. “Choose another plot” can be clearer than an error containing the plot's full name and reference. If a reference helps the applicant distinguish selections, render it as a separate value inside the translated sentence:
<p lang="ar" dir="rtl"> القطعة <bdi dir="ltr">GDN-R6-284</bdi> لم تعد متاحة. اختر قطعة أخرى.</p>This example defines a boundary for a known Latin reference. It does not claim the unwrapped reference is visibly broken: a value beginning with Latin letters can stay intact without isolation. The boundary makes the component's intent explicit when the reference format changes. Use bidi isolation for the underlying rules.
In a live component, create the value node and assign its textContent. Do not turn an interpolated value into HTML merely because the translation supports markup. Keep the translator-controlled sentence structure and the application-controlled value boundary distinct.
Counts need separate attention. Arabic cardinal plurals have six categories, which Intl.PluralRules can select. The category alone does not supply a grammatical sentence. Review the complete messages for counts selecting zero, one, two, few, many and other.
If the summary only needs to direct attention, a reviewed heading such as راجع الحقول التالية. avoids a counted noun altogether. Use a count when it helps navigation, then translate its forms properly rather than importing the English singular-versus-plural pattern.
Make the error reachable and keep it current#
For multiple failures, provide a summary with links naming the affected fields, then place the specific correction by each field. After a failed submit, move focus to the summary or first invalid control according to the form's design. W3C's form notification guidance describes these patterns and field-to-error associations.
Choose one announcement strategy and test it with your supported assistive technology. Focusing a summary while also firing several assertive alerts can make the same failure compete with itself. Inline text associated through aria-describedby is useful when a field receives focus, but association alone is not a promise that every dynamic update will be announced immediately.
Do not move focus on every keystroke. After submission, updating an existing error while the applicant corrects that field can help. Before submission, avoid treating a half-written answer as a completed attempt. The planting-plan example waits for the first submit attempt before showing its missing-value error.
For asynchronous validation, tie the result to the value that was checked. Suppose plot A starts an availability request, the applicant selects plot B, and A's rejection arrives last. Applying that response to the current selection would falsely reject B. Use a request generation or equivalent state check before displaying the result; canceling older requests is useful but does not replace checking relevance.
Conditional fields need the same discipline. Remove errors for branches the applicant no longer needs, update the summary and ensure every correction link reaches a visible, usable control. A translated message pointing into a collapsed or removed branch still blocks progress.
Let longer Arabic corrections change the layout#
An inline error needs room to wrap. Do not position it over the following field or reserve a fixed single-line slot based on its English translation. Test the longest real Arabic correction while the help text is also present.
#garden-request { max-inline-size: 36rem;} #plan-error { margin-block: 0.6rem 1rem; text-align: start; overflow-wrap: anywhere;}This keeps the message in normal flow and allows long tokens to wrap. It does not establish whether the whole form fits a particular screen; inspect the complete component at narrow widths and increased text size. Avoid hiding overflow to make an error look shorter, because the missing words may contain the correction.
If an error is cut off, debug its actual container before changing the translation to fit. Arabic text getting cut off in CSS covers those layout causes. Shorten wording for clarity, not to conceal a box that cannot accommodate its content.
Test the failures, then test their removal#
Keep the interface locale Arabic while varying browser language. That separates catalog coverage from browser-owned wording. Test the browsers you support directly; the measured Chromium result does not establish Safari or Firefox behavior.
For the garden application, these fixtures exercise distinct paths:
| State to create | What to verify |
|---|---|
| Submit with an untouched planting plan | Arabic correction appears; focus reaches its field or summary |
| Enter only spaces | The application applies its stated missing-content rule |
| Correct the plan and submit again | Old text, invalid state and error association are removed |
| Have the selected plot become unavailable | The server code produces an Arabic plot-specific correction |
| Change plots while validation is pending | An older response cannot reject the new selection |
| Return an unknown server error code | A usable Arabic fallback appears without exposing diagnostics |
| Switch language with errors already visible | Summary, inline text and accessible descriptions update together |
| Retry after a request failure | Entries remain available and the request outcome is handled correctly |
Also test keyboard submission where the control supports it, not only pointer activation of the submit button. The form's validation policy should not depend on a button click handler that another submission path never runs.
During correction, inspect the input's associated description IDs and aria-invalid alongside the visible paragraph. A screenshot cannot reveal a stale accessible error after the paragraph has disappeared. Conversely, an accessible association does not prove the Arabic text fits on screen. Check both, using the actual translations and current font.
A free Ritla scan can report : Untranslated form labels / validation / help text. Reproduce the failed-submit and server-error states during your own review too; Arabic localization testing helps organize that review around the messages applicants actually encounter.