Недавно я шукав інформацію про формати позначень мов, щоб написати обробник 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})+)