【问题标题】:How to convert IETF BCP 47 language identifier to ISO-639-2?如何将 IETF BCP 47 语言标识符转换为 ISO-639-2?
【发布时间】:2014-09-28 13:53:16
【问题描述】:

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

问题在于 Apple 在其 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,它无处不在,有多种语言的许多解析器,并且具有标准的三字母语言表示。

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

【问题讨论】:

    标签: python ios iso-639-2 ietf-bcp-47


    【解决方案1】:

    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
    

    我不希望 Apple 使用 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'
    

    terminology 形式是首选的 3 字母代码;还有一个 bibliography 表格,它仅对 22 个条目有所不同。见ISO 639-2 B and T codes。但是,该软件包不包括 ISO 639-5 中的条目;该列表在某些地方与 639-2 重叠和冲突,我认为 Apple 根本不使用此类代码。

    【讨论】:

    • 谢谢!这将使解析变得容易得多。请问你有这个事实的参考吗?
    • @AdamMatan:为您添加了 RFC 参考。
    • 639 不仅仅是 639-1 和 639-2。 3 个字符的 iso 639 语言代码可以是 639-3。
    • @FabianKessler:对,还有 639-5,尽管这个列表相当稀疏。 pycountry 不包括它。
    【解决方案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 代码,尽管它们可能不是三个字母的变体。 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 字符变体的转换应该很容易处理,因为映射是众所周知的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-06-20
      • 1970-01-01
      • 2011-07-06
      • 2013-05-03
      • 1970-01-01
      • 2015-05-30
      • 2011-09-20
      相关资源
      最近更新 更多