2014-09-28 98 views
4

我正在为iOS应用程序编写服务器API。作为初始化过程的一部分,应用程序应通过API调用将电话界面语言发送到服务器。如何将IETF BCP 47语言标识符转换为ISO-639-2?

问题是苹果在其NSLocale preferredLanguages function中使用了一种叫IETF BCP 47 language identifier的东西。

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

我想用比较常见的ISO-639-2 three-letters language identifier,这是无处不在的,已许多解析器在许多语言,并拥有语言标准,3个字母表示。

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

回答

7

BCP 47标识符以2字母ISO 639-1 3字母639-2,639-3或639-5语言代码开头;看到RFC 5646 Syntax section

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 

我并不指望苹果使用privateusegrandfathered形式,所以你可以假设你正在寻找ISO 639-1,ISO 639-2,ISO 639 -3或ISO 639-5语言代码。只需将2个字母的ISO-639-1代码映射到3个字母的ISO 639- *代码即可。

可以使用pycountry package此:

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' 

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

+0

谢谢!这将使解析变得更容易。你有没有参考这个事实? – 2014-09-28 14:20:50

+0

@AdamMatan:为您添加RFC参考。 – 2014-09-28 14:28:05

+0

639不只是639-1和639-2。一个3字符的iso 639语言代码可以是639-3。 – 2015-02-01 20:20:35

1

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代码尽管他们可能不是三个字母变体。一个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" 

一良好的开端是类似以下内容:从2个字符的变型的3个字符的变种

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) 

转换应该是很容易处理,因为映射是众所周知的。