语法
语言标签由一个或多个“子标签”的序列组成,每个子标签都会细化或缩小整个标签所表示的语言范围。子标签是一个由字母和数字组成的序列,被连字符(“-”,[[Unicode]] U+002D)与语言标签中的其他子标签区分开来。
子标签有不同类型,每种子标签都可以通过长度、在语言标签中的位置和子标签本身的内容中进行区分:每个子标签的类型可以只由这些特性来识别。即使没有识别出特定的子标签值,也可以从子标签中提取出一些语义信息。因此,语言标签处理器没有有效标签或子标签的列表(即IANA语言子标签注册中心的某个版本的副本)也可执行常见的搜索和匹配操作。唯一的例外是在下面的推导规则regular
和irregular
中列出的旧版标签。这些标签是在 [[RFC3066]] 下注册的,并且是一个永远不会改变的固定列表。
用 ABNF [[RFC5234]] 表示的语言标签的语法如下:
Language-Tag = langtag ; 普通的语言标签
/ privateuse ; 私用标签
/ grandfathered ; 旧版标签
langtag = language
["-" script]
["-" region]
*("-" variant)
*("-" extension)
["-" privateuse]
language = 2*3ALPHA ; 最短的 ISO 639 代码
["-" extlang] ; 有时后面有
; 扩展语言子标签
/ 4ALPHA ; 或保留以备将来使用
/ 5*8ALPHA ; 或为注册的语言子标签
extlang = 3ALPHA ; 选定的 ISO 639 代码
*2("-" 3ALPHA) ; 永久保留
script = 4ALPHA ; ISO 15924 代码
region = 2ALPHA ; ISO 3166-1 代码
/ 3DIGIT ; UN M.49 代码
variant = 5*8alphanum ; 已注册的变种
/ (DIGIT 3alphanum)
extension = singleton 1*("-" (2*8alphanum))
; 单个字母或数字
; "x" 保留私用
singleton = DIGIT ; 0 - 9
/ %x41-57 ; A - W
/ %x59-5A ; Y - Z
/ %x61-77 ; a - w
/ %x79-7A ; y - z
privateuse = "x" 1*("-" (1*8alphanum))
grandfathered = irregular ; 已注册的非冗余标签
/ regular ; 在 RFC 3066 时期
irregular = "en-GB-oed" ; 不规则标签与langtag推导规则不匹配,
/ "i-ami" ; 不被认为是“符合语法规则的”。
/ "i-bnn" ; 虽然不规则标签签是有效的,
/ "i-default" ; 但是其中的大多数标签已不推荐使用,
/ "i-enochian" ; 推荐使用更现代的子标签或子标签组合
/ "i-hak"
/ "i-klingon"
/ "i-lux"
/ "i-mingo"
/ "i-navajo"
/ "i-pwn"
/ "i-tao"
/ "i-tay"
/ "i-tsu"
/ "sgn-BE-FR"
/ "sgn-BE-NL"
/ "sgn-CH-DE"
regular = "art-lojban" ; 这些标签与langtag推导规则相匹配,
/ "cel-gaulish" ; 但是它们的子标签不是扩展语言或变体子标签:
/ "no-bok" ; 它们的含义由它们的注册来定义,
/ "no-nyn" ; 为了支持更现代的子标签或子标签序列,
/ "zh-guoyu" ; 不建议使用所有这些子标签
/ "zh-hakka"
/ "zh-min"
/ "zh-min-nan"
/ "zh-xiang"
alphanum = (ALPHA / DIGIT) ; 字母和数字
有关语言标签的示例,请参见TODO
所有子标签的最大长度为8个字符,语言标签中不允许使用空格。ABNF中的variant
推导规则有一个微妙之处:以数字开头的变体的最小长度为4个字符,而以字母开头的变体的最小长度为5个字符。
尽管 [[RFC5234]] 使用的是8位数据(octets),本文档中描述的语言标签使用 US-ASCII [[ISO646]] 字符集的中的字符组成的序列。语言标签可(MAY)用于使用其他编码的文档和应用程序中,只要它们包含 US-ASCII 字符集的相关部分即可。使用 [[Unicode]] 的 UTF-16LE [[RFC2781]] 编码的 XML 文档就是一个例子。
语言标签的格式
在任何时候,语言标签及其子标签(包括私用和扩展)都不应区分大小写:某些子标签习惯上使用大写,但不得(MUST NOT)带有任何语义。
因此,标签mn-Cyrl-MN
与MN-cYRL-mn
或mN-cYrL-Mn
(或任何其他组合)没有区别,并且这些变体均传达相同的含义:在蒙古使用的用西里尔字母写成的蒙古语。
ABNF语法也不区分大写和小写:A至Z范围内的大写US-ASCII字母等同并映射到a至Z范围内的US-ASCII小写字母。因此,标签I-AMI
被认为等同于irregular
推导规则中的值i-ami
。
尽管区分大小写在语言标签中不包含语义,格式一致的和语言标签将对用户有所帮助。建议(RECOMMENDED)将注册中心中子标签的格式作为在语言标签中使用的形式。此格式通常和对应的ISO标准中约定的格式相同。
这些约定包括:
- [[ISO-639-1]] 建议使用小写字母编写语言代码(蒙古语
mn
)。
- [[ISO15924]] 建议使用首字母大写、其他字母小写的形式编写文字代码(西里尔字母
Cyrl
)。
- [[ISO3166-1]] 建议将国家代码大写(蒙古
MN
)。
本文档的实现无需访问注册中心即可重现此格式,规则如下:所有子标签,包括扩展和私用子标签,均使用小写字母,但有两个例外。这两个例外是:不出现在标签的开头以及单字符子标签之后的2个字母和4个字母的子标签。这样的2个字母的子标签都是大写的(例如在标签en-CA-x-ca
或sgn-BE-FR
中),而4个字母的子标签是首字母大写的(例如在标签az-Latn-x-latn
)。
注意:在某些语言环境中,ASCII字母的大小写转换(除非仔细处理)有时会产生非ASCII字符值。Unicode字符数据库文件“SpecialCasing.txt” [[SpecialCasing]] 定义了导致此问题的特定情况。尤其是土耳其语和阿塞拜疆语中的字母“i”(U+0069)的大写为U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE。实现者应(SHOULD)实现一个与语言环境无关的大小写操作,以确保子标签的大小写转换不会产生该值,因为这在语言标签中是非法的。例如,如果使用在土耳其语环境中将区域子标签in
大写,则将产生序列 U+0130 U+004E,而不是预期的IN
。