Javascript 策略重复命名捕获组,因此您必须将 ?<privateUse> 的第二次使用更改为例如?<privateUse1>。编译为:
/^((?<grandfathered>(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)|(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang))|((?<language>([A-Za-z]{2,3}(-(?<extlang>[A-Za-z]{3}(-[A-Za-z]{3}){0,2}))?)|[A-Za-z]{4}|[A-Za-z]{5,8})(-(?<script>[A-Za-z]{4}))?(-(?<region>[A-Za-z]{2}|[0-9]{3}))?(-(?<variant>[A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3}))*(-(?<extension>[0-9A-WY-Za-wy-z](-[A-Za-z0-9]{2,8})+))*(-(?<privateUse>x(-[A-Za-z0-9]{1,8})+))?)|(?<privateUse1>x(-[A-Za-z0-9]{1,8})+))$/
这是一种构造方法:
let privateUseUsed = 0
const privateUse = () => "(?<privateUse" + (privateUseUsed++) + ">x(-[A-Za-z0-9]{1,8})+)"
const grandfathered = "(?<grandfathered>" +
/* irregular */ (
"en-GB-oed" +
"|" + "i-(?:ami|bnn|default|enochian|hak|klingon|lux|mingo|navajo|pwn|tao|tay|tsu)" +
"|" + "sgn-(?:BE-FR|BE-NL|CH-DE)"
) +
"|" + /* regular */ (
"art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang"
) +
")"
const langtag = "(" +
"(?<language>" + (
"([A-Za-z]{2,3}(-" +
"(?<extlang>[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>[A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3})" + ")*" +
"(-" + "(?<extension>" + (
/* singleton */ "[0-9A-WY-Za-wy-z]" +
"(-[A-Za-z0-9]{2,8})+)"
) +
")*" +
"(-" + privateUse() + ")?" +
")"
const languageTagReStr = "^(" + grandfathered + "|" + langtag + "|" + privateUse() + ")$";
编辑:原来 ff 不支持命名的捕获组,所以你必须用.replace(/\?<a-zA-Z>/g, '') 将它们去掉,或者一开始就把它们排除在外:
const grandfathered = "(" +
/* irregular */ "(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)" +
"|" +
/* regular */ "(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang)" +
")";
const langtag = "(" +
"(" + (
"([A-Za-z]{2,3}(-" +
"([A-Za-z]{3}(-[A-Za-z]{3}){0,2})" +
")?)|[A-Za-z]{4}|[A-Za-z]{5,8})"
) +
"(-" + "([A-Za-z]{4})" + ")?" +
"(-" + "([A-Za-z]{2}|[0-9]{3})" + ")?" +
"(-" + "([A-Za-z0-9]{5,8}|[0-9][A-Za-z0-9]{3})" + ")*" +
"(-" + "(" + (
/* singleton */ "[0-9A-WY-Za-wy-z]" +
"(-[A-Za-z0-9]{2,8})+)"
) +
")*" +
"(-" + "(x(-[A-Za-z0-9]{1,8})+)" + ")?" +
")";
const languageTag = RegExp("^(" + grandfathered + "|" + langtag + "|" + "(x(-[A-Za-z0-9]{1,8})+)" + ")$");
用languageTag.test('en-us')测试