Недавно я шукав інформацію про формати позначень мов, щоб написати обробник http-запитів на одному сайті (для таких полів http-заголовків як "Accept-Language"), і знайшов трохи корисної інформації, якою хочу поділитись. Просто залишу посилання тут.
Accept-Language (rfc7231)
Language Tag (rfc5646)
ISO 639-2 (.txt);
3-буквенні коди мовних сімейств і груп : Alpha-3 code for language families and groups.
upd:
Створив регулярний вираз для перевірки на валідність Language-Tag:
(([A-Za-z]{2,3}(\-[A-Za-z]{3}(\-[A-Za-z]{3}){0,2})?|[A-Za-z]{4,8})(\-[A-Za-z]{4})?(\-([A-Za-z]{2}|[0-9]{3}))?(\-([0-9A-Za-z]{5,8}|[0-9][0-9A-Za-z]{3}))*(\-[0-9A-WYZa-wyz](\-[0-9A-Za-z]{2,8})+)*(\-x(\-[0-9A-Za-z]{1,8})+)?|x(\-[0-9A-Za-z]{1,8})+|en\-[A-Z]{2}\-oed|i\-[a-z]{3,8}|sgn(\-[A-Z]{2}){2}|[a-z]{2,3}(\-[a-z]{3,8})+)
"майже строго" по стандарту.
▼Етапи формування регулярного виразу
1)
#    langtag
#        language
#            2*3ALPHA
                [A-Za-z]{2,3}
#            ["-" extlang]
#                3ALPHA
                    [A-Za-z]{3}
#                *2("-" 3ALPHA)
                    (\-[A-Za-z]{3}){0,2}
#            / 4ALPHA / 5*8ALPHA
                [A-Za-z]{4,8}
#        ["-" script]
#            4ALPHA            # ISO 15924
                [A-Za-z]{4}
#        ["-" region]
#            2ALPHA            # ISO 3166-1
                [A-Za-z]{2}
#            / 3DIGIT        # UN M.49 code
                [0-9]{3}
#        *("-" variant)
#            5*8alphanum
                [0-9A-Za-z]{5,8}
#            / (DIGIT 3alphanum)
                [0-9][0-9A-Za-z]{3}
#        *("-" extension)
#            singleton 1*("-" (2*8alphanum))
                [0-9A-WYZa-wyz](\-[0-9A-Za-z]{2,8})+
#        ["-" privateuse]
#            "x" 1*("-" (1*8alphanum))
                x(\-[0-9A-Za-z]{1,8})+
#    / privateuse
#        "x" 1*("-" (1*8alphanum))
            x(\-[0-9A-Za-z]{1,8})+
#    / grandfathered
#        irregular
            en\-[A-Z]{2}\-oed
            |i\-[a-z]{3,8}
            |sgn(\-[A-Z]{2}){2}
#        / regular
            [a-z]{2,3}(\-[a-z]{3,8})+
2)
#Language-Tag
#    langtag
#        language
            ([A-Za-z]{2,3}(\-[A-Za-z]{3}(\-[A-Za-z]{3}){0,2})?|[A-Za-z]{4,8})
#        ["-" script]
            (\-[A-Za-z]{4})?
#        ["-" region]
            (\-([A-Za-z]{2}|[0-9]{3}))?
#        *("-" variant)
            (\-([0-9A-Za-z]{5,8}|[0-9][0-9A-Za-z]{3}))*
#        *("-" extension)
            (\-[0-9A-WYZa-wyz](\-[0-9A-Za-z]{2,8})+)*
#        ["-" privateuse]
            (\-x(\-[0-9A-Za-z]{1,8})+)?
#    / privateuse
        x(\-[0-9A-Za-z]{1,8})+
#    / grandfathered
#        irregular
            (en\-[A-Z]{2}\-oed|i\-[a-z]{3,8}|sgn(\-[A-Z]{2}){2})
#        / regular
            [a-z]{2,3}(\-[a-z]{3,8})+
3)
#Language-Tag
#    langtag
        ([A-Za-z]{2,3}(\-[A-Za-z]{3}(\-[A-Za-z]{3}){0,2})?|[A-Za-z]{4,8})(\-[A-Za-z]{4})?(\-([A-Za-z]{2}|[0-9]{3}))?(\-([0-9A-Za-z]{5,8}|[0-9][0-9A-Za-z]{3}))*(\-[0-9A-WYZa-wyz](\-[0-9A-Za-z]{2,8})+)*(\-x(\-[0-9A-Za-z]{1,8})+)?
#    / privateuse
        x(\-[0-9A-Za-z]{1,8})+
#    / grandfathered
        (en\-[A-Z]{2}\-oed|i\-[a-z]{3,8}|sgn(\-[A-Z]{2}){2}|[a-z]{2,3}(\-[a-z]{3,8})+)
4)
#Language-Tag
    (([A-Za-z]{2,3}(\-[A-Za-z]{3}(\-[A-Za-z]{3}){0,2})?|[A-Za-z]{4,8})(\-[A-Za-z]{4})?(\-([A-Za-z]{2}|[0-9]{3}))?(\-([0-9A-Za-z]{5,8}|[0-9][0-9A-Za-z]{3}))*(\-[0-9A-WYZa-wyz](\-[0-9A-Za-z]{2,8})+)*(\-x(\-[0-9A-Za-z]{1,8})+)?|x(\-[0-9A-Za-z]{1,8})+|en\-[A-Z]{2}\-oed|i\-[a-z]{3,8}|sgn(\-[A-Z]{2}){2}|[a-z]{2,3}(\-[a-z]{3,8})+)