def parse_subtags(subtags, expect=EXTLANG):
    """
    Parse everything that comes after the language tag: scripts, regions,
    variants, and assorted extensions.
    """
    # We parse the parts of a language code recursively: each step of
    # language code parsing handles one component of the code, recurses
    # to handle the rest of the code, and adds what it found onto the
    # list of things that were in the rest of the code.
    #
    # This could just as well have been iterative, but the loops would have
    # been convoluted.
    #
    # So here's the base case.
    if not subtags:
        return []

    # There's a subtag that comes next. We need to find out what it is.
    #
    # The primary thing that distinguishes different types of subtags is
    # length, but the subtags also come in a specified order. The 'expect'
    # parameter keeps track of where we are in that order. expect=REGION,
    # for example, means we're expecting a region code, or anything later
    # (because everything but the language is optional).
    subtag = subtags[0]
    tag_length = len(subtag)

    # In the usual case, our goal is to recognize what kind of tag this is,
    # and set it in 'tagtype' -- as an integer, so we can compare where it
    # should go in order. You can see the enumerated list of tagtypes above,
    # where the SUBTAG_TYPES global is defined.
    tagtype = None

    if tag_length == 0 or tag_length > 8:
        # Unless you're inside a private use tag or something -- in which case,
        # you're not in this function at the moment -- every component needs to
        # be between 1 and 8 characters.
        subtag_error(subtag, '1-8 characters')

    elif tag_length == 1:
        # A one-character subtag introduces an extension, which can itself have
        # sub-subtags, so we dispatch to a different function at this point.
        #
        # We don't need to check anything about the order, because extensions
        # necessarily come last.
        return parse_extension(subtags)

    elif tag_length == 2:
        if subtag.isalpha():
            # Two-letter alphabetic subtags are regions. These are the only
            # two-character subtags after the language.
            tagtype = REGION

    elif tag_length == 3:
        if subtag.isalpha():
            # Three-letter alphabetic subtags are 'extended languages'.
            # It's allowed for there to be up to three of them in a row, so we
            # need another function to enforce that. Before we dispatch to that
            # function, though, we need to check whether we're in the right
            # place in order.
            if expect <= EXTLANG:
                return parse_extlang(subtags)
            else:
                order_error(subtag, EXTLANG, expect)
        elif subtag.isdigit():
            # Three-digit subtags are broad regions, such as Latin America
            # (419).
            tagtype = REGION

    elif tag_length == 4:
        if subtag.isalpha():
            # Four-letter alphabetic subtags are scripts.
            tagtype = SCRIPT
        elif subtag[0].isdigit():
            # Four-character subtags that start with a digit are variants.
            tagtype = VARIANT

    else:
        # Tags of length 5-8 are variants.
        tagtype = VARIANT

    # That's the end of the big elif block for figuring out what kind of
    # subtag we have based on its length. Now we should do something with that
    # kind of subtag.

    if tagtype is None:
        # We haven't recognized a type of tag. This subtag just doesn't fit the
        # standard.
        subtag_error(subtag)

    elif tagtype < expect:
        # We got a tag type that was supposed to appear earlier in the order.
        order_error(subtag, tagtype, expect)

    else:
        # We've recognized a subtag of a particular type. If it's a region or
        # script, we expect the next subtag to be a strictly later type, because
        # there can be at most one region and one script. Otherwise, we expect
        # the next subtag to be the type we got or later.

        if tagtype in (SCRIPT, REGION):
            expect = tagtype + 1
        else:
            expect = tagtype

        # Get the name of this subtag type instead of its integer value.
        typename = SUBTAG_TYPES[tagtype]

        # Some subtags are conventionally written with capitalization. Apply
        # those conventions.
        if tagtype == SCRIPT:
            subtag = subtag.title()
        elif tagtype == REGION:
            subtag = subtag.upper()

        # Recurse on the remaining subtags.
        return [(typename, subtag)] + parse_subtags(subtags[1:], expect)
def parse_subtags ( subtags , expect = EXTLANG ) : if not subtags : return [ ] subtag = subtags [ 0 ] tag_length = len ( subtag ) tagtype = None if tag_length == 0 or tag_length > 8 : subtag_error ( subtag , '1-8 characters' ) elif tag_length == 1 : return parse_extension ( subtags ) elif tag_length == 2 : if subtag . isalpha ( ) : tagtype = REGION elif tag_length == 3 : if subtag . isalpha ( ) : if expect <= EXTLANG : return parse_extlang ( subtags ) else : order_error ( subtag , EXTLANG , expect ) elif subtag . isdigit ( ) : tagtype = REGION elif tag_length == 4 : if subtag . isalpha ( ) : tagtype = SCRIPT elif subtag [ 0 ] . isdigit ( ) : tagtype = VARIANT else : tagtype = VARIANT if tagtype is None : subtag_error ( subtag ) elif tagtype < expect : order_error ( subtag , tagtype , expect ) else : if tagtype in ( SCRIPT , REGION ) : expect = tagtype + 1 else : expect = tagtype typename = SUBTAG_TYPES [ tagtype ] if tagtype == SCRIPT : subtag = subtag . title ( ) elif tagtype == REGION : subtag = subtag . upper ( ) return [ ( typename , subtag ) ] + parse_subtags ( subtags [ 1 : ] , expect )
Parse everything that comes after the language tag: scripts, regions,
    variants, and assorted extensions.