“Do I need to translate text alternatives?”
Writing accessible content like alt text and ARIA labels can be challenging. If your website supports multiple languages, then there’s an added layer of complexity to consider—what information should and should not be translated?
On the tech side, there are multiple ways to translate a website.
- You can serve up different HTML files, each written in their own language.
- You can tokenize the content so it’s a bunch of variable names in the source code that get swapped out for the correct language before rendering.
- You can use a translation proxy that swaps out content on the fly before it hits the user’s browser.
Regardless of which approach you take, you need to know which words you translate and which you don’t. This gets tricky when some of those words are only exposed to people using assistive technology! Things like CSS tricks and ARIA attributes hide information from sighted developers making them easy to miss. So, here’s a guide for all you developers out there who are asking questions like “do I need to translate text alternatives?”
If you’re just looking for the quick cheat sheet of which attributes and text nodes to include, feel free to jump to the Summary list at the end. Otherwise, read on Macduff!
Attribute values
In general, you must translate attributes if their value is an authorable string instead of a tokenized value or ID reference. It’s possible that URL-based attributes like src
or href
may need to be localized (for example, if the files you’re referencing have a country or language in their folder structure). But that’s not necessarily the same as being translated, so I’m leaving them off the list.
Note: tokenized values mean that the attribute’s value must match one of a pre-defined list of options. For example, type, autocomplete, role, and aria-expanded all have tokenized values.
HTML attributes
Translate: Yes
There are a handful of common attributes in HTML that render text to the user (either visually, or through assistive technology).
title
– provides an accessible name for some elements (like an<iframe>
) or provides an accessible description if the element already has a name. The value also displays as hover text when using a mouse.alt
– provides a text alternative to image-based content like<img>
or<input type="image">
. Thealt
attribute’s value also displays in the image’s place if that image fails to load.placeholder
– shows hint text in a form field until the user starts to type (worth noting that the placeholder attribute isn’t favorable in accessibility).
A few less common attributes you may encounter are:
enterkeyhint
– customizes the “Enter” key text on a virtual keyboard.label
– sets the title text when selecting subtitle or caption tracks in a video player.
Here’s a fun word of the day: autoglossonym. This is when a language’s name is written in its own language (for example, Español for Spanish or Français for French). Autoglossonyms are relevant because whether language names are written in the page language vs. their own language will determine if they need to be translated in certain attributes.
Let’s use the HTML <video>
element with multiple caption tracks as an example.
<video controls src="pirates-of-the-caribbean.mp4">
<track src="caption_en.vtt" kind="captions" srclang="en" label="English">
<track src="caption_tlh.vtt" kind="captions" srclang="tlh" label="Klingon">
</video>
Within the <video>
element’s UI, there’s a menu for selecting different caption tracks. The <track>
element’s label
attribute defines the text for each menu option.
If the label is written as an autoglossonym, then there’s no need to translate it (just make sure you have the lang
attribute set on each <track>
). But if each label is written in the page language (like in the screenshot), make sure you translate it! (And as it turns out, some languages do have translations for the word Klingon!)
ARIA attributes
Translate: Yes
Conveniently, the ARIA specification already has a section for translatable states and properties. It lists these 4 attributes:
aria-label
– used to assign an accessible name to semantic components.aria-placeholder
– like the native HTMLplaceholder
attribute. It provides hint text for custom form controls where the native attribute can’t be used.aria-roledescription
– overrides a component’s default role with an author-defined value.aria-valuetext
– assigns a human readable text value to a range widget such as a volume slider.
In the next ARIA spec version (1.3), W3C proposes a new attribute called aria-description. This attribute has the same purpose as aria-describedby
, but instead of using an ID reference its value is an authorable string (similar to aria-label
vs. aria-labelledby
). I’m including this in the Summary list at the end of the article since it’s already starting to get browser support, even though version 1.3 is still just a working draft as of writing this.
Global attributes
Translate: No
Besides title
, global HTML attributes like id
and class
must not be translated. These are often used for scripting or presentational purposes and shouldn’t be tied to the language on the page. Translating these would likely break functionality or break the visual presentation.
<section id="section-1" class="container">...</section>
Most global HTML and ARIA attributes are either tokenized or reference an HTML ID. These values are interpreted by machines, not by people. Even though the tokenized values are written in English, they should never be translated. Doing so would break a machine’s ability to parse the code correctly.
For example, even though the word “banner” (representing an ARIA landmark role) is written in English, and the page language is Spanish, the code should stay like this:
<html lang="es">
<body>
<div role="banner">...</div>
...
</body>
</html>
The banner role must not be translated like this:
<html lang="es">
<body>
<div role="bandera">...</div>
...
</body>
</html>
CSS content
Translate: Yes (but…)
There’s one edge-case where you can technically render text on the page using CSS properties (though it’s arguably a bad practice to do so). I’m talking about the CSS content
property. You see this property used with the pseudo-elements ::before
and ::after
. For example, this code would append the text “Email me at” to the beginning of any mailto link.
a[href^="mailto:"]::before {
content: "Email me at ";
}
The text “Email me at” also gets added to the link’s accessible name and needs to be translated. I say this is arguably bad practice because now you’re translating content inside stylesheets which blurs the line between content and presentation assets.
Hidden text nodes
Text nodes in your markup can be hidden in several different ways while still being read by assistive technology. Since users can still perceive this text, it must be translated.
Visually-hidden
Translate: Yes
If you come across class names like .sr-only
or .visually-hidden
, these are common examples of a CSS trick for writing content that doesn’t appear on screen but is still available to assistive technology.
<span class="visually-hidden">Do you read me?</span>
In short, the text renders with a size of zero so it doesn’t take up any space. But it’s still included in the accessibility tree. If you want to learn all there is to know about this technique, I highly recommend reading The anatomy of visually-hidden by James Edwards.
Hidden but referenced
Translate: Yes
The HTML hidden
attribute or the CSS display:none
and visibility:hidden
properties can also be used to hide content. But in this case, it’s hidden from everyone (unless it isn’t).
Consider this markup:
<fieldset>
<legend>Did you find this article helpful?</legend>
<button aria-pressed="false">Yes</button>
<button aria-pressed="false" aria-describedby="follow-up">No</button>
<div hidden id="follow-up">Triggers dialog with follow-up questions</div>
</fieldset>
This example asks for “Yes” or “No” feedback about an article. Pressing “No” changes the user’s context by launching a dialog, so it’s trying to warn people using screen readers about that change in advance. The <div>
element with the warning text isn’t included in the accessibility tree because of the HTML hidden
attribute. But it’s still announced by screen readers as the button’s description because of the aria-describedby
attribute.
Even though this node is never unhidden, it’s still announced by screen readers with the rest of the button’s properties. So it needs to be translated!
Fallback content
Translate: Yes
Sometimes websites include fallback content for certain scenarios. A common example is the <noscript>
element. This element lets you define content that displays if JavaScript is disabled in the user’s browser. Other elements like the HTML5 <video>
element supports fallback content if the browser doesn’t support that element.
It’s easy to forget about fallback content since, by design, it only shows if the primary content fails. But when someone encounters that fallback content, they’ll want to know what it says. So make sure it’s translated for them!
Summary
Translate values for these attributes:
title
alt
placeholder
enterkeyhint
label
(unless the value is written in its own language)aria-label
aria-placeholder
aria-roledescription
aria-valuetext
aria-description
Translate all text nodes, even if they’re hidden with one of these methods:
hidden
attributedisplay:none
in the CSSvisibility:none
in the CSS- CSS tricks like
.sr-only
and.visually-hidden
- Fallback elements like
<noscript>
Don’t translate other global attributes or those that use tokenized values or ID references. For example:
id
class
autocomplete
role
aria-labelledby
aria-describedby
aria-pressed
aria-live
- and so on…
And just avoid using the CSS content
property for rendering text or images that require text alternatives. It’s not worth the hassle.
Comments