主导航中不能放入语言切换器,因其语义是页面间跳转,而语言切换是视图刷新,行为本质冲突;必须用独立包裹原生,并同步更新document.documentElement.lang、URL路径与localStorage。

主导航里不能塞语言切换按钮
主导航(<nav aria-label="主导航"></nav>)的语义是“跳转到不同页面或锚点”,而语言切换是“刷新/重载当前页或切换视图”,二者行为本质冲突。把语言选择器(比如 <select id="language-select"></select>)直接放进 <nav></nav> 会导致屏幕阅读器误报为“主导航的一部分”,键盘 Tab 焦点逻辑混乱,且 SEO 可能将语言选项当作独立入口页抓取。
常见错误现象:Uncaught TypeError: Cannot read property 'value' of null(JS 找不到 language-select),或切换后 document.documentElement.lang 没变、URL 路径没更新、屏幕阅读器仍用原语言朗读。
- 语言切换必须独立于主导航,推荐用
<div role="navigation" aria-label="语言选择"> 包裹 <li>若 UI 上需视觉靠近主导航(如右对齐),可用 CSS 布局实现,但 DOM 结构必须分离</li> <li>禁止在 <code><nav aria-label="主导航"></nav>内放<select></select>、<button></button>或表单控件 - 多语言站点中,主导航链接本身也需带
hreflang属性,例如:<a href="/zh/about" hreflang="zh-CN">关于我们</a> -
<select></select>必须有id(如id="language-select"),否则 JS 获取不稳定 -
<option value></option>必须是标准 BCP 47 标签:en-US、zh-CN、ja——禁用chinese、zh_CN、zh(后者在部分浏览器 fallback 为und) - 默认项应写成:
<option disabled selected value="">Language</option>,避免空值触发误切换 - 切换时必须同步执行三件事:
document.documentElement.lang = 'zh-CN'、URL 路径替换(如/about → /zh/about)、localStorage.setItem('preferred-lang', 'zh-CN') - 每个语言版本应部署在独立子目录(
/、/en/、/zh/),而非同一 HTML 文件内靠 JS 切换 -
必须在 HTML 源码中真实存在,不能靠 JS 首屏后注入——否则 Safari 字体回退、Chrome 语音合成、NVDA 断句都会出错 - 主导航中所有链接的
href必须与当前语言路径前缀一致,不可用相对路径(如../about.html)或无前缀路径(如about.html) - 构建时可通过模板引擎(如 Eleventy)自动注入语言前缀和
hreflang,纯静态页则需手动维护或脚本批量生成 - 主导航:
<nav aria-label="主导航"></nav>(不是“主菜单”或“顶部导航”) - 语言切换容器:
<nav aria-label="语言选择"></nav>(注意:不是“语言导航”,因它不跳转页面) - 页脚链接组:
<nav aria-label="页脚资源链接"></nav>(不是“页脚导航”,避免与可操作导航混淆) - 移动端抽屉菜单:
<nav aria-label="移动菜单"></nav>,并配合aria-hidden控制隐藏状态
语言切换器必须用原生 <select></select>,且带标准 BCP 47 value
自定义下拉(如 <div> + <code><ul></ul>)会破坏键盘导航、屏幕阅读器播报和移动端原生体验。原生 <select></select> 是唯一被所有辅助技术一致支持的语言选择控件。
关键实操点:
立即学习“前端免费学习笔记(深入)”;
主导航链接要配合 hreflang 和语言子目录结构
单纯靠 JS 切换语言文字,对 SEO 和无障碍是无效的。真正可落地的多语言导航,依赖服务端路径隔离 + 客户端语义补全。
比如用户在 /en/products 页面,主导航中的「关于我们」链接不应是 /about,而必须是:<a href="/en/about" hreflang="en-US">About Us</a>。同理,中文版对应链接是 <a href="/zh/about" hreflang="zh-CN">关于我们</a>。
多个 <nav></nav> 共存时,aria-label 必须用途明确
一个页面常有主导航、语言切换区、页脚链接组、移动端折叠菜单等,它们都用 <nav></nav>,但语义角色完全不同。全写 aria-label="导航" 等于没写。
正确做法是按功能命名,不模糊、不复用:
容易被忽略的是:这些 <nav></nav> 的 DOM 顺序、嵌套层级和是否包裹真实可跳转链接,直接影响读屏器播报顺序和焦点流。语言切换器哪怕视觉上在右上角,DOM 位置也建议放在 <header></header> 内主导航之后,符合用户心智模型。



















