About This HTML Issue
The first part of a lang value has to be a language code made of letters, like en or fr, and the validator rejects a wildcard, an underscore, a digit or a template placeholder in that position.
The lang attribute takes a BCP 47 language tag: subtags joined by hyphens, starting with the language subtag. That first subtag is almost always a two- or three-letter ISO 639 code like en, pt or ast, optionally followed by a region (en-GB), a script (zh-Hant) or other registered subtags. When the language subtag contains a character that isn't a letter, the validator reports it with this message. A code that has the right shape but isn't registered, such as zz, gets a different error saying it is not a valid ISO language part of a language tag.
A few patterns cause most of these errors. The * wildcard means "any language" in the Accept-Language HTTP header, but it isn't a language tag, and a template that prints a stored language setting can output it when content is marked as being for all languages. Locale names such as en_US or fr_FR use an underscore, which HTML doesn't accept as a separator, so the validator reads the whole value as one subtag and shows it in lowercase (fr_fr) in the message. Unreplaced placeholders like %LANG% or {lang} fail the same way.
Replace the value with the tag for the language the content is written in. On a multilingual page, put the main language on <html> and give passages in other languages their own lang. Screen readers use this value to pick a voice and pronunciation rules, and browsers use it for hyphenation and spell checking. Neither can do that with *.
Invalid example
The document language is a wildcard, and the French paragraph uses a locale name with an underscore:
<!DOCTYPE html>
<html lang="*">
<head>
<meta charset="utf-8">
<title>Opening hours</title>
</head>
<body>
<p>The library opens at 9:00 every weekday.</p>
<p lang="fr_FR">La bibliothèque ouvre à 9 h en semaine.</p>
</body>
</html>
Valid example
English on the root element, and a hyphenated tag for the French paragraph:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Opening hours</title>
</head>
<body>
<p>The library opens at 9:00 every weekday.</p>
<p lang="fr-FR">La bibliothèque ouvre à 9 h en semaine.</p>
</body>
</html>
Find issues like this automatically
Rocket Validator scans thousands of pages in seconds, detecting HTML issues across your entire site.