diff --git a/__tests__/src/rules/lang-test.js b/__tests__/src/rules/lang-test.js index 810bebc77..7096bc508 100644 --- a/__tests__/src/rules/lang-test.js +++ b/__tests__/src/rules/lang-test.js @@ -30,6 +30,10 @@ ruleTester.run('lang', rule, { { code: '
;' }, { code: '' }, { code: '' }, + { code: '' }, + { code: '' }, + { code: '' }, + { code: '' }, { code: '' }, { code: '' }, { code: '' }, diff --git a/docs/rules/lang.md b/docs/rules/lang.md index 50ec74db3..ce133afd4 100644 --- a/docs/rules/lang.md +++ b/docs/rules/lang.md @@ -1,17 +1,19 @@ # lang -The `lang` prop on the `` element must have a valid value based on ISO country and language codes. +The `lang` prop on the `` element must be a valid IETF's BCP 47 language tag. #### References + 1. [axe-core, valid-lang](https://dequeuniversity.com/rules/axe/3.2/valid-lang) -2. [ISO Language Codes](http://www.w3schools.com/tags/ref_language_codes.asp) -3. [ISO Country Codes](http://www.w3schools.com/tags/ref_country_codes.asp) +2. [Language tags in HTML and XML](https://www.w3.org/International/articles/language-tags/) +3. [IANA Language Subtag Registry](https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry) ## Rule details This rule takes no arguments. ### Succeed + ```jsx diff --git a/package.json b/package.json index 330e2f202..a8bfaf7eb 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,8 @@ "damerau-levenshtein": "^1.0.6", "emoji-regex": "^9.0.0", "has": "^1.0.3", - "jsx-ast-utils": "^2.4.1" + "jsx-ast-utils": "^2.4.1", + "language-tags": "^1.0.5" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7" diff --git a/src/rules/lang.js b/src/rules/lang.js index 0cdb59a65..7c1efb315 100644 --- a/src/rules/lang.js +++ b/src/rules/lang.js @@ -8,8 +8,8 @@ // ---------------------------------------------------------------------------- import { propName, elementType, getLiteralPropValue } from 'jsx-ast-utils'; +import tags from 'language-tags'; import { generateObjSchema } from '../util/schemas'; -import ISO_CODES from '../util/attributes/ISO.json'; const errorMessage = 'lang attribute must have a valid value.'; @@ -51,12 +51,7 @@ module.exports = { return; } - const hyphen = value.indexOf('-'); - const lang = hyphen > -1 ? value.substring(0, hyphen) : value; - const country = hyphen > -1 ? value.substring(3) : undefined; - - if (ISO_CODES.languages.indexOf(lang) > -1 - && (country === undefined || ISO_CODES.countries.indexOf(country) > -1)) { + if (tags.check(value)) { return; } diff --git a/src/util/attributes/ISO.json b/src/util/attributes/ISO.json deleted file mode 100644 index 4beb9b555..000000000 --- a/src/util/attributes/ISO.json +++ /dev/null @@ -1,390 +0,0 @@ -{ - "countries": [ - "AF", - "AL", - "DZ", - "AS", - "AD", - "AO", - "AI", - "AQ", - "AG", - "AR", - "AM", - "AW", - "AU", - "AT", - "AZ", - "BS", - "BH", - "BD", - "BB", - "BY", - "BE", - "BZ", - "BJ", - "BM", - "BT", - "BO", - "BA", - "BW", - "BR", - "IO", - "VG", - "BN", - "BG", - "BF", - "MM", - "BI", - "KH", - "CM", - "CA", - "CV", - "KY", - "CF", - "TD", - "CL", - "CN", - "CX", - "CC", - "CO", - "KM", - "CK", - "CR", - "HR", - "CU", - "CY", - "CZ", - "CD", - "DK", - "DJ", - "DM", - "DO", - "EC", - "EG", - "SV", - "GQ", - "ER", - "EE", - "ET", - "FK", - "FO", - "FJ", - "FI", - "FR", - "PF", - "GA", - "GM", - "GE", - "DE", - "GH", - "GI", - "GR", - "GL", - "GD", - "GU", - "GT", - "GN", - "GW", - "GY", - "HT", - "VA", - "HN", - "HK", - "HU", - "IS", - "IN", - "ID", - "IR", - "IQ", - "IE", - "IM", - "IL", - "IT", - "CI", - "JM", - "JP", - "JE", - "JO", - "KZ", - "KE", - "KI", - "KW", - "KG", - "LA", - "LV", - "LB", - "LS", - "LR", - "LY", - "LI", - "LT", - "LU", - "MO", - "MK", - "MG", - "MW", - "MY", - "MV", - "ML", - "MT", - "MH", - "MR", - "MU", - "YT", - "MX", - "FM", - "MD", - "MC", - "MN", - "ME", - "MS", - "MA", - "MZ", - "NA", - "NR", - "NP", - "NL", - "AN", - "NC", - "NZ", - "NI", - "NE", - "NG", - "NU", - "KP", - "MP", - "NO", - "OM", - "PK", - "PW", - "PA", - "PG", - "PY", - "PE", - "PH", - "PN", - "PL", - "PT", - "PR", - "QA", - "CG", - "RO", - "RU", - "RW", - "BL", - "SH", - "KN", - "LC", - "MF", - "PM", - "VC", - "WS", - "SM", - "ST", - "SA", - "SN", - "RS", - "SC", - "SL", - "SG", - "SK", - "SI", - "SB", - "SO", - "ZA", - "KR", - "ES", - "LK", - "SD", - "SR", - "SJ", - "SZ", - "SE", - "CH", - "SY", - "TW", - "TJ", - "TZ", - "TH", - "TL", - "TG", - "TK", - "TO", - "TT", - "TN", - "TR", - "TM", - "TC", - "TV", - "UG", - "UA", - "AE", - "GB", - "US", - "UY", - "VI", - "UZ", - "VU", - "VE", - "VN", - "WF", - "EH", - "YE", - "ZM", - "ZW" - ], - - "languages": [ - "ab", - "aa", - "af", - "sq", - "am", - "ar", - "an", - "hy", - "as", - "ay", - "az", - "ba", - "eu", - "bn", - "dz", - "bh", - "bi", - "br", - "bg", - "my", - "be", - "km", - "ca", - "zh", - "zh-Hans", - "zh-Hant", - "co", - "hr", - "cs", - "da", - "nl", - "en", - "eo", - "et", - "fo", - "fa", - "fj", - "fi", - "fr", - "fy", - "gl", - "gd", - "gv", - "ka", - "de", - "el", - "kl", - "gn", - "gu", - "ht", - "ha", - "he", - "iw", - "hi", - "hu", - "is", - "io", - "id", - "in", - "ia", - "ie", - "iu", - "ik", - "ga", - "it", - "ja", - "jv", - "kn", - "ks", - "kk", - "rw", - "ky", - "rn", - "ko", - "ku", - "lo", - "la", - "lv", - "li", - "ln", - "lt", - "mk", - "mg", - "ms", - "ml", - "mt", - "mi", - "mr", - "mo", - "mn", - "na", - "ne", - "no", - "oc", - "or", - "om", - "ps", - "pl", - "pt", - "pa", - "qu", - "rm", - "ro", - "ru", - "sm", - "sg", - "sa", - "sr", - "sh", - "st", - "tn", - "sn", - "ii", - "sd", - "si", - "ss", - "sk", - "sl", - "so", - "es", - "su", - "sw", - "sv", - "tl", - "tg", - "ta", - "tt", - "te", - "th", - "bo", - "ti", - "to", - "ts", - "tr", - "tk", - "tw", - "ug", - "uk", - "ur", - "uz", - "vi", - "vo", - "wa", - "cy", - "wo", - "xh", - "yi", - "ji", - "yo", - "zu" - ] -}