diff --git a/src/validate/html/a11y.ts b/src/validate/html/a11y.ts
index 205a6388f5..94061e9b19 100644
--- a/src/validate/html/a11y.ts
+++ b/src/validate/html/a11y.ts
@@ -143,6 +143,11 @@ export default function a11y(
shouldHaveAttribute(['title']);
}
+ // html-has-lang
+ if (node.name === 'html') {
+ shouldHaveAttribute(['lang']);
+ }
+
// no-distracting-elements
if (node.name === 'marquee' || node.name === 'blink') {
validator.warn(`A11y: Avoid <${node.name}> elements`, node.start);
@@ -168,4 +173,4 @@ function getValue(attribute: Node) {
if (attribute.value.length === 1 && attribute.value[0].type === 'Text') return attribute.value[0].data;
return null;
-}
\ No newline at end of file
+}
diff --git a/test/validator/samples/a11y-html-has-lang/input.html b/test/validator/samples/a11y-html-has-lang/input.html
new file mode 100644
index 0000000000..41f2fc6276
--- /dev/null
+++ b/test/validator/samples/a11y-html-has-lang/input.html
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/test/validator/samples/a11y-html-has-lang/warnings.json b/test/validator/samples/a11y-html-has-lang/warnings.json
new file mode 100644
index 0000000000..fc1066cffe
--- /dev/null
+++ b/test/validator/samples/a11y-html-has-lang/warnings.json
@@ -0,0 +1,10 @@
+[
+ {
+ "loc": {
+ "column": 0,
+ "line": 5
+ },
+ "message": "A11y: element should have a lang attribute",
+ "pos": 82
+ }
+ ]