如何将IETF BCP 47语言标识符转换为ISO-639-2?

我正在为iOS应用程序编写一个服务器API。 作为初始化过程的一部分,应用程序应通过API调用将电话界面语言发送到服务器。

问题是苹果在NSLocale preferredLanguages函数中使用了一种叫做IETF BCP 47语言标识符的东西。

返回的值具有不同的长度(例如[aa, ab, ace, ach, ada, ady, ae, af, afa, afh, agq, ...] ,而且我发现很less的parsing器可以将此代码转换为适当的语言标识符。

我想使用更普遍的ISO-639-2三字母语言标识符 ,它是无处不在的,在许多语言中有许多parsing器,并且具有标准的3个字母的语言表示。

如何将IETF BCP 47语言标识符转换为ISO-639-2三字母语言标识符,最好是在Python中?

BCP 47标识符以2字母ISO 639-1 3字母639-2,639-3或639-5语言代码开始; 请参阅RFC 5646语法部分 :

 Language-Tag = langtag ; normal language tags / privateuse ; private use tag / grandfathered ; grandfathered tags langtag = language ["-" script] ["-" region] *("-" variant) *("-" extension) ["-" privateuse] language = 2*3ALPHA ; shortest ISO 639 code ["-" extlang] ; sometimes followed by ; extended language subtags / 4ALPHA ; or reserved for future use / 5*8ALPHA ; or registered language subtag 

我不希望苹果公司使用privateuseprivateuseforms,所以你可以假设你在这里查看ISO 639-1,ISO 639-2,ISO 639-3或ISO 639-5语言代码。 只需将两个字母的ISO-639-1代码映射到三个字母的ISO 639- *代码即可。

你可以使用pycountry包来pycountry这一点:

 import pycountry lang = pycountry.languages.get(alpha2=two_letter_code) three_letter_code = lang.terminology 

演示:

 >>> import pycountry >>> lang = pycountry.languages.get(alpha2='aa') >>> lang.terminology u'aar' 

其中术语forms是优选的三字母代码; 还有一个参考书目forms,只有22个条目不同。 参见ISO 639-2 B和T代码 。 该软件包不包括来自ISO 639-5的条目。 该列表与639-2重叠并与之冲突,我认为苹果公司根本不使用这种代码。

从RFC5646 / BCP47 :

 Language-Tag = langtag ; normal language tags / privateuse ; private use tag / grandfathered ; grandfathered tags langtag = language ["-" script] ["-" region] *("-" variant) *("-" extension) ["-" privateuse] language = 2*3ALPHA ; shortest ISO 639 code ["-" extlang] ; sometimes followed by ; extended language subtags / 4ALPHA ; or reserved for future use / 5*8ALPHA ; or registered language subtag privateuse = "x" 1*("-" (1*8alphanum)) grandfathered = irregular ; non-redundant tags registered / regular ; during the RFC 3066 era 

看起来大多数BCP-47代码的第一部分应该是有效的ISO-639代码,尽pipe它们可能不是三字母变体。 BCP-47语言代码有一些不是ISO-639代码的变体,即那些以x-i-开始的代码,以及一些与语法的grandfathered部分相匹配的遗留代码:

 irregular = "en-GB-oed" ; irregular tags do not match / "sgn-BE-FR" ; also includes i- prefixed codes / "sgn-BE-NL" / "sgn-CH-DE" regular = "art-lojban" ; these tags match the 'langtag' / "cel-gaulish" ; production, but their subtags / "no-bok" ; are not extended language / "no-nyn" ; or variant subtags: their meaning / "zh-guoyu" ; is defined by their registration / "zh-hakka" ; and all of these are deprecated / "zh-min" ; in favor of a more modern / "zh-min-nan" ; subtag or sequence of subtags / "zh-xiang" 

一个好的开始将是如下的东西:

 def extract_iso_code(bcp_identifier): language, _ = bcp_identifier.split('-', 1) if 2 <= len(language) <=3: # this is a valid ISO-639 code or is grandfathered else: # handle non-ISO codes raise ValueError(bcp_identifier) 

由于映射是众所周知的,因此从2个字符的变体到3个字符的变体应该很容易处理。

Interesting Posts