语言代码对照表
常见语言的 ISO 639-1 两字母代码与中英文名称,用于网页 lang 属性、多语言 API 与内容协商。
原理解析
ISO 639 为自然语言分配代码:两位(zh、en、ja)与三位(zho、eng、jpn)。它们用于 HTML lang 属性、Content-Language 头、语言切换器等,比中文/英文名称更通用。
地区常叠加在语言之后,形成语言标签(BCP 47):zh-CN、en-US、pt-BR——前者是语言、后者是地区变体。同一语言不同地区在拼写、用词、日期格式上可能差异明显,i18n 必须区分。
实务上的最小可用做法:页面根元素标 lang,内容较长且语言不同的片段单独标 lang/hreflang,路由段只用 ISO 639-1 两字母并在需要地区差异时才追加地区码。这三步能覆盖绝大多数场景的可访问性与 SEO 需求,成本很低。真正需要额外投入的是内容本身的多语言版本管理(翻译、复数规则、日期与数字格式),那属于 i18n 工程而非语言代码问题,不要在代码层面找解法。
关于「代码」与「标签」的一个常见误解:ISO 639 只覆盖语言,不覆盖文字系统。像 he(希伯来语)这类语言可能使用拉丁或希伯来文字,zh-Hant 与 zh-Hans 的差异是文字系统而非语言,处理排版与字体时要看 script 子标签而不是语言码。日常 Web 场景语言码足够,但做多文字排版或无障碍朗读时,script 层的影响会显现出来。
什么时候该查这张表
这张表在你要给内容打上语言标记时有用:HTML lang 属性、HTTP Content-Language 头、搜索筛选、朗读与翻译路由,全都以语言代码为依据。打错的后果是搜索引擎读不懂页面语种、屏幕阅读器选错语音、hreflang 关系失效。
不该查的情况:你在做界面文案的多语言版本管理。语言代码解决的是「这段内容是什么语言」,而 i18n 文件的组织、复数规则、日期格式属于 i18n 工程范畴,两者不要混。
判断标准:凡是「机器需要据此做选择」的地方就写代码——lang、Accept-Language、hreflang;凡是「人看的界面」就写语言名或 Intl.DisplayNames 的结果。两者混用是常见错误来源。
特别注意两字母与三字母不是简单长短关系:ISO 639-1 的 zh 是「整个中文」,639-2/T 的 zho 是文献语言名,639-3 的 zho 则是 macrolanguage 集合(可细到 cmn/yue)。写数据库主键时必须明确选用哪一版,混用会造成静默的匹配失败。
边界与常见陷阱
lang 属性写在错误的元素上会继承错语言
lang 是可继承属性。整页有多语言混排(如中文正文里嵌一段英文代码示例)时,只在 <html> 上写一次 lang="zh" 会让屏幕阅读器用中文读英文段落。可行的做法是给语言不同的片段单独标 lang="en",必要时再加 dir 指示书写方向;搜索引擎也能据此判断段落语种而非整页语种。
hreflang 必须双向互指且用规范 URL
声明 en-US 指向 /en/x 的同时,/en/x 那一侧也必须回指 zh-CN,否则搜索引擎会忽略这组关系。三个细节常导致失效:① 用的 URL 带查询参数或缺少尾部斜杠,与实际 canonical 不一致;② 写了 x-default 但没指向任何真实版本;③ 相对 URL 与绝对 URL 混用。
Accept-Language 的 q 值决定优先级而非质量
q=0.9 表示偏好度而不是「这个语言有 90% 的质量」。q=0 是显式排除,不是省略。真实场景里浏览器会发送一长串语言(连 q=0.05 的小语种也有),服务端应当解析前几个高 q 值做匹配,而不是拿整个列表当过滤器——否则一个含 30 种语言的请求会命中一条你没准备好的翻译。
语言代码与地区变体混用会造成路由错配
zh 与 zh-CN 都能表示中文,但不是同一个值:前者是 macrolanguage,后者特指大陆简体。同理 en 覆盖全部英语区,en-US / en-GB / en-AU 在拼写、日期、数字格式上差异真实存在。若 URL 设计成 /en/ 而内容里写 en-US,链接会指向一个不存在的路由。设计路由时语言段要统一用 ISO 639-1 两字母,地区信息放在查询参数或独立段落。
与相邻内容的分工
要查字符层面的编码方案(UTF-8、GBK、Shift-JIS 怎么把字符变成字节),用站内「字符编码」页;本页是语言标签(BCP 47 / ISO 639)层面的标识。
地区与国家代码(ISO 3166)、货币代码(ISO 4217)不在本页范围,站内另有对应速查页。
需要把日期、数字按目标语言格式化,用 Intl.DateTimeFormat / Intl.NumberFormat 配合本页的语言代码;本页不提供格式化实现。
若目的是让搜索引擎正确识别多语言站点的页面归属,hreflang 关系比 lang 属性更关键,且需双向互指。
实战片段
要点:① lang 是可继承属性,混排片段必须单独标注,否则屏幕阅读器会用整页语音读外语段落;② hreflang 必须双向互指且 URL 与 canonical 完全一致(含尾部斜杠),x-default 要指向真实存在的那一版;③ Accept-Language 的 q 是偏好度不是质量,q=0 是排除不是省略,解析时只取前几个高 q 值并归一到两字母,否则长列表会命中没准备的翻译。
<html lang="zh-CN">
<head>
<link rel="alternate" hreflang="zh-CN" href="https://oltool.net/reference/language-codes.html">
<link rel="alternate" hreflang="en" href="https://oltool.net/en/reference/language-codes.html">
<link rel="alternate" hreflang="x-default" href="https://oltool.net/reference/language-codes.html">
</head>
<body>
<p>中文正文,浏览器会选中文语音朗读。</p>
<!-- 混排片段单独标注,否则会被整页 lang 覆盖 -->
<p>
参考 ISO 639-1,
<span lang="en">the two-letter code list</span>
共收录 184 种语言。
</p>
</body>
</html>
<!-- 解析 Accept-Language:只取前几个高 q 值,不要拿全表当过滤器 -->
function negotiate(header?: string | null): string {
const raw = (header ?? '').split(',').map(part => {
const [tag, ...params] = part.trim().split(';')
const q = params.find(p => p.trim().startsWith('q='))
return { tag: tag.trim(), q: q ? Number(q.split('=')[1]) : 1 }
})
return raw
.filter(x => x.q > 0 && x.tag !== '*') // q=0 是显式排除
.sort((a, b) => b.q - a.q)
.slice(0, 3) // 只匹配前 3 个,其余可能没有翻译
.map(x => x.tag.split('-')[0]) // 归一到 ISO 639-1 两字母
.join(',') || 'en'
}实践注解
- ISO 639-1 与 639-2/3 的粒度不同639-1 是两字母(zh、en),639-3 覆盖到方言级(cmn 官话、yue 粤语)。中文场景里 zh 与 zh-Hans/zh-Hant 也不是同一层级:前者是语言,后者带文字系统。
- BCP 47 的取值顺序有约定俗成zh-Hans-CN 依次是语言-文字-地区。只写 zh 时,字体选定、排序规则都要靠运行环境猜测,跨系统结果不一致;面向简体用户应显式写 zh-Hans。
- 内容协商别只看 Accept-Language 的第一个值它带 q 权重且可能列出用户看不懂的语言。服务端应按权重排序并与已有译文求交集,全都不可用时回退到默认语言,而不是机械取首项。
数据来源
- ISO 639-1 / 639-2 / 639-3
- IETF BCP 47 (RFC 5646)
- IANA Language Subtag Registry
上述编号、名称与定义均来自公开规范,本站不主张对规范数据本身的独创性;本页的编排方式、中文释义与实践注解由本站撰写。
| ISO 639-1 | 语言(中) | 语言(英) |
|---|---|---|
| zh | 中文 | Chinese |
| en | 英语 | English |
| es | 西班牙语 | Spanish |
| fr | 法语 | French |
| de | 德语 | German |
| ja | 日语 | Japanese |
| ko | 韩语 | Korean |
| ru | 俄语 | Russian |
| pt | 葡萄牙语 | Portuguese |
| it | 意大利语 | Italian |
| ar | 阿拉伯语 | Arabic |
| hi | 印地语 | Hindi |
| nl | 荷兰语 | Dutch |
| sv | 瑞典语 | Swedish |
| pl | 波兰语 | Polish |
| tr | 土耳其语 | Turkish |
| vi | 越南语 | Vietnamese |
| th | 泰语 | Thai |
常见问题
ISO 639-1 和 ISO 639-2 有什么区别?
639-1 是两字母代码(如 zh、en),覆盖最常用的约 180+ 种语言,最常用于网页 lang 属性与 API。639-2 是三字母代码(如 zho、eng),覆盖更全、含更多濒危语言,常用于图书馆与文献编目。
Accept-Language 请求头怎么用?
客户端在请求里带 Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,服务端据此挑选最近的语言返回,权重 q 表示优先级。多语言站点应读取它做内容协商(配合 cookie/URL 让用户可覆盖)。
zh-CN 和 zh-TW 是 ISO 639 代码吗?
不是。zh 是 ISO 639-1 的语言码,CN/TW 是 ISO 3166 的地区码;"zh-CN"/"zh-TW" 是「语言-地区」组合,用于区分简体/繁体与区域习惯,但地区部分来自国家代码标准而非语言标准。
如何表示方言或地区变体(如 en-US、pt-BR)?
用「语言码-地区码」格式:语言取 ISO 639-1,地区取 ISO 3166-1 Alpha-2。en-US=美式英语,pt-BR=巴西葡萄牙语。地区部分可选,用于日期/货币/措辞本地化。