最可靠方式是直接读取 document.documentelement.lang,它原生支持、准确反映 html 根元素 lang 属性(含动态修改),默认返回空字符串而非 undefined,兼容现代浏览器,且应优先于 navigator.language 使用。

直接读取 document.documentElement.lang 最可靠
浏览器原生支持,无需额外库,且能准确反映当前 HTML 根元素的 lang 属性值(包括动态修改后的状态)。注意它不依赖 navigator.language 或服务器响应头,只看 DOM 实际渲染时的 这类声明。
常见错误是误用 document.body.lang 或 document.querySelector('html').getAttribute('lang') —— 前者可能为空(body 不一定设 lang),后者在属性缺失时返回 null,而 document.documentElement.lang 在未声明时默认返回空字符串 "",行为更一致。
- 如果 HTML 没写
lang,document.documentElement.lang是"",不是undefined - 支持动态变更:比如执行
document.documentElement.lang = 'ja'后立即读取,值同步更新 - 兼容所有现代浏览器,包括 Safari 10+、Chrome 5+、Firefox 4+
当需要 fallback 到浏览器语言时,谨慎组合 navigator.language
navigator.language 返回的是用户系统/浏览器设置的语言(如 zh-CN、en-US),和页面实际声明的 lang 是两回事。仅在明确需要“用户偏好语言”而非“页面当前语言”时才用它,比如做 i18n 资源预加载。
容易踩的坑:navigator.language 在部分旧版 iOS Safari 中返回 undefined;某些隐私模式下可能被限制;还存在 navigator.languages(数组)与 navigator.language(字符串)的差异。
- 优先用
document.documentElement.lang || navigator.language || 'en'做降级,但要清楚每层含义不同 - 不要用
navigator.language替代lang属性校验——它不能告诉你页面是否已正确标记双语切换 - SSR 场景下该值不可用(服务端无
navigator),需靠请求头Accept-Language补充
检测多语言切换是否生效:监听 lang 变更不现实,改用 MutationObserver
HTML 的 lang 属性本身不触发 languagechange 事件(那是 window 对象为 navigator.language 变更设计的,且支持度极差)。真要响应页面语言切换,只能监听根元素属性变化。
const observer = new MutationObserver(() => {
const currentLang = document.documentElement.lang;
console.log('lang changed to:', currentLang);
});
observer.observe(document.documentElement, { attributes: true, attributeFilter: ['lang'] });
- 必须指定
attributeFilter: ['lang'],否则会收到大量无关变动通知 - 首次运行不会触发回调,需手动调用一次初始化逻辑
- React/Vue 等框架中,若语言切换走的是状态驱动(如 class 切换或 data- 属性),这个 Observer 依然有效——只要最终改到了
服务端渲染(SSR)场景下,前端脚本无法早于 HTML 解析执行
像 Next.js、Nuxt 这类框架中,document.documentElement.lang 在 useEffect 或 mounted 钩子中才可用;若在 getServerSideProps 或 asyncData 中试图读取,会报 ReferenceError: document is not defined。
此时关键点是:语言信息必须从服务端透出,比如通过 <script>window.__LANG__ = "zh-CN"</script> 注入全局变量,或把语言作为 props 传给组件。
- 避免在 SSR 组件顶层直接访问
document—— 服务端没 DOM - 前端 hydration 后,仍应以
document.documentElement.lang为准,而不是信任注入的变量(防篡改/竞态) - 如果页面语言由 URL 决定(如
/en/about),服务端应同步设置,否则前后端不一致会导致 layout shift 或翻译错乱
实际项目中最容易被忽略的,是假设 lang 属性一旦设置就永远不变,或默认它和用户语言一致。真实场景里,语言切换常伴随 CSS 方向(dir)、字体加载、甚至第三方 SDK(如 Sentry、Plausible)的语言配置,这些都得和 document.documentElement.lang 保持同步,而不是各自查 navigator。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











