html-validate需手动启用lang-valid规则并配置required标签列表和allow语言白名单,才能强制语义化容器显式设置lang属性,否则仅根节点lang声明会导致title、alt等可访问性功能失效。

html-validate 怎么校验 lang 属性是否显式设置
html-validate 默认不检查 lang 属性是否被显式写在每个语义化容器上,只当它缺失时才报错。但实际问题在于:仅设 document.documentElement.lang 会导致 <title>、<alt>、标点间距、字体回退全部失效——这不是警告,是可访问性硬伤。
必须手动启用并配置规则:"lang-required": true 只管根节点;真正要的是 "lang-valid": true + 自定义白名单。示例配置片段:
{
"rules": {
"lang-valid": ["error", {
"allow": ["en", "zh", "zh-HK", "ja", "ko"],
"required": ["h1", "h2", "p", "section", "article", "blockquote", "pre"]
}]
}
}
-
required列表里的标签,只要出现就必须带lang,否则直接 CI 失败 -
allow是你项目支持的语言码,非法值(如lang="cn")会被拦截 -
<pre lang="bash">这类已有lang的元素,不会被覆盖——它属于多语言混排,不是错误
data-i18n 属性漏标导致的校验盲区怎么暴露
html-validate 不会主动扫描 data-i18n 是否缺失,但它能通过自定义规则抓出“本该翻译却没标记”的结构性风险。比如 placeholder、title、aria-label 这些属性,前端常只给 textContent 加 data-i18n,结果切换语言后输入框提示仍是英文,屏幕阅读器读错内容。
可行做法是写一条轻量级自定义规则(放在 .htmlvalidate.json 的 customRules 中):
立即学习“前端免费学习笔记(深入)”;
module.exports = {
"data-i18n-missing-attr": {
"meta": { "type": "problem" },
"create": function(context) {
return {
"Element": function(node) {
const attrs = ["placeholder", "title", "aria-label", "aria-placeholder"];
for (const attr of attrs) {
if (node.attribs[attr] && !node.attribs["data-i18n-" + attr]) {
context.report({
node: node,
message: `Missing data-i18n-${attr} on element with ${attr}="${node.attribs[attr]}"`
});
}
}
}
};
}
}
};
- 这条规则会在 CI 中报出所有带
placeholder却没配data-i18n-placeholder的<input> - 不用改源码,只需把文件存为
rules/i18n-attrs.js,并在配置里引用:"customRules": ["./rules/i18n-attrs.js"] - 注意:不要对
value或src做此检查——它们不是用户可见文案,不该翻译
HTML 自动排版(HAL)规则能否被 html-validate 检查
html-validate 本身不内置 HAL(HTML Automatic Layout)校验,比如“避免绝对定位”“允许文本换行”“用 max-width 替代固定宽”这类布局适配多语言的实践,它无法从 HTML 结构推断出来。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
但你可以用 CSS 校验补位:启用 stylelint 并加载 stylelint-a11y 和 stylelint-scss 插件,在 CI 中并行跑。关键规则包括:
-
"a11y/no-obsolete-attribute": true—— 拦截align、valign等已废弃属性,它们会破坏多语言文本流 -
"declaration-no-important": true—— 防止用!important锁死尺寸,阻碍 RTL 或长文本撑开 -
"selector-max-id": 0—— 强制用 class 而非 ID 控制样式,方便按语言加特定 class 如lang-zh-hk
真正难的是:HAL 不是语法错误,而是设计决策。它必须靠 code review + checklist + PR 模板来守住,比如在 GitHub PR 描述里强制勾选:“✅ 所有按钮/输入框宽度使用 max-content 或 fit-content,未用 width: 120px”。
国际化页面的语义结构校验为什么比普通页面更严格
普通 HTML 校验关注闭合、嵌套、属性合法性;而国际化页面还要确保结构本身不隐含语言偏见。例如:<time datetime="2023-01-01">Jan 1</time> 在中文环境应显示“1月1日”,但若没配 datetime 或格式错误,Intl API 就会 fallback 到浏览器默认语言——结果用户看到英文日期,还无法修正。
必须额外校验三类结构:
-
<time>必须带合法datetime,且值匹配^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2})?Z?$;可用"time-req-datetime": true规则 -
<ol>在 RTL 语言(如阿拉伯语)中需加dir="rtl",否则序号方向反了;html-validate 支持"dir-required": ["error", ["ol", "ul"]] -
<input type="date">必须配合novalidate+ JS 手动校验,否则原生提示无法国际化;可在 CI 中 grep 检查:grep -r 'type="date"' src/ | grep -v 'novalidate'
最易被忽略的是:校验器只看源码,不运行 JS。所以即使你写了完美 setCustomValidity(),html-validate 也看不到——它只提醒你“这里用了 date input,但没关默认校验”,逼你在提交前补上 novalidate。


















