lighthouse 10.2.0-dev.20230522 → 10.2.0-dev.20230524

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,10 @@
1
+ export default HTMLXMLLangMismatch;
2
+ declare class HTMLXMLLangMismatch extends AxeAudit {
3
+ }
4
+ export namespace UIStrings {
5
+ const title: string;
6
+ const failureTitle: string;
7
+ const description: string;
8
+ }
9
+ import AxeAudit from './axe-audit.js';
10
+ //# sourceMappingURL=html-xml-lang-mismatch.d.ts.map
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @license Copyright 2023 The Lighthouse Authors. All Rights Reserved.
3
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
4
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
5
+ */
6
+
7
+ /**
8
+ * @fileoverview Ensures that, if present, the `[xml:lang]` attribute value in an HTML document has
9
+ * the same base language as the `[lang]` attribute.
10
+ * See base class in axe-audit.js for audit() implementation.
11
+ */
12
+
13
+ import AxeAudit from './axe-audit.js';
14
+ import * as i18n from '../../lib/i18n/i18n.js';
15
+
16
+ const UIStrings = {
17
+ /** Title of an accesibility audit that evaluates if the xml:lang attribute, if present, has the same base language as the `lang` attribute. This title is descriptive of the successful state and is shown to users when no user action is required. */
18
+ title: '`<html>` element has an `[xml:lang]` attribute with the same base language as the ' +
19
+ '`[lang]` attribute.',
20
+ /** Title of an accesibility audit that evaluates if the xml:lang attribute, if present, has the same base language as the `lang` attribute. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed. */
21
+ failureTitle: '`<html>` element does not have an `[xml:lang]` attribute with the same base ' +
22
+ 'language as the `[lang]` attribute.',
23
+ /** Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. The last sentence starting with 'Learn' becomes link text to additional documentation. */
24
+ description: 'If the webpage does not specify a consistent language, then the screen ' +
25
+ 'reader might not announce the page\'s text correctly. ' +
26
+ '[Learn more about the `lang` attribute](https://dequeuniversity.com/rules/axe/4.7/html-xml-lang-mismatch).',
27
+ };
28
+
29
+ const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
30
+
31
+ class HTMLXMLLangMismatch extends AxeAudit {
32
+ /**
33
+ * @return {LH.Audit.Meta}
34
+ */
35
+ static get meta() {
36
+ return {
37
+ id: 'html-xml-lang-mismatch',
38
+ title: str_(UIStrings.title),
39
+ failureTitle: str_(UIStrings.failureTitle),
40
+ description: str_(UIStrings.description),
41
+ requiredArtifacts: ['Accessibility'],
42
+ };
43
+ }
44
+ }
45
+
46
+ export default HTMLXMLLangMismatch;
47
+ export {UIStrings};
@@ -0,0 +1,10 @@
1
+ export default InputButtonName;
2
+ declare class InputButtonName extends AxeAudit {
3
+ }
4
+ export namespace UIStrings {
5
+ const title: string;
6
+ const failureTitle: string;
7
+ const description: string;
8
+ }
9
+ import AxeAudit from './axe-audit.js';
10
+ //# sourceMappingURL=input-button-name.d.ts.map
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @license Copyright 2023 The Lighthouse Authors. All Rights Reserved.
3
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
4
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
5
+ */
6
+
7
+ /**
8
+ * @fileoverview Ensures input buttons have discernible text.
9
+ * See base class in axe-audit.js for audit() implementation.
10
+ */
11
+
12
+ import AxeAudit from './axe-audit.js';
13
+ import * as i18n from '../../lib/i18n/i18n.js';
14
+
15
+ const UIStrings = {
16
+ /** Title of an accesibility audit that evaluates if all input buttons have discernible text. This title is descriptive of the successful state and is shown to users when no user action is required. */
17
+ title: 'Input buttons have discernible text.',
18
+ /** Title of an accesibility audit that evaluates if all input buttons have discernible text. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed. */
19
+ failureTitle: 'Input buttons do not have discernible text.',
20
+ /** Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. The last sentence starting with 'Learn' becomes link text to additional documentation. */
21
+ description: 'Adding discernable and accessible text to input buttons may help screen reader ' +
22
+ 'users understand the purpose of the input button. ' +
23
+ '[Learn more about input buttons](https://dequeuniversity.com/rules/axe/4.7/input-button-name).',
24
+ };
25
+
26
+ const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
27
+
28
+ class InputButtonName extends AxeAudit {
29
+ /**
30
+ * @return {LH.Audit.Meta}
31
+ */
32
+ static get meta() {
33
+ return {
34
+ id: 'input-button-name',
35
+ title: str_(UIStrings.title),
36
+ failureTitle: str_(UIStrings.failureTitle),
37
+ description: str_(UIStrings.description),
38
+ requiredArtifacts: ['Accessibility'],
39
+ };
40
+ }
41
+ }
42
+
43
+ export default InputButtonName;
44
+ export {UIStrings};
@@ -0,0 +1,10 @@
1
+ export default TableFakeCaption;
2
+ declare class TableFakeCaption extends AxeAudit {
3
+ }
4
+ export namespace UIStrings {
5
+ const title: string;
6
+ const failureTitle: string;
7
+ const description: string;
8
+ }
9
+ import AxeAudit from './axe-audit.js';
10
+ //# sourceMappingURL=table-fake-caption.d.ts.map
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @license Copyright 2023 The Lighthouse Authors. All Rights Reserved.
3
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
4
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
5
+ */
6
+
7
+ /**
8
+ * @fileoverview Ensure that tables use `<caption>` instead of colspan for a caption.
9
+ * See base class in axe-audit.js for audit() implementation.
10
+ */
11
+
12
+ import AxeAudit from './axe-audit.js';
13
+ import * as i18n from '../../lib/i18n/i18n.js';
14
+
15
+ const UIStrings = {
16
+ /** Title of an accesibility audit that evaluates if all tables use caption instead of colspan to indicate a caption. This title is descriptive of the successful state and is shown to users when no user action is required. */
17
+ title: 'Tables use `<caption>` instead of cells with the `[colspan]` attribute to indicate a ' +
18
+ 'caption.',
19
+ /** Title of an accesibility audit that evaluates if all tables use caption instead of colspan to indicate a caption. This title is descriptive of the failing state and is shown to users when there is a failure that needs to be addressed. */
20
+ failureTitle: 'Tables do not use `<caption>` instead of cells with the `[colspan]` attribute ' +
21
+ 'to indicate a caption.',
22
+ /** Description of a Lighthouse audit that tells the user *why* they should try to pass. This is displayed after a user expands the section to see more. No character length limits. The last sentence starting with 'Learn' becomes link text to additional documentation. */
23
+ description: 'Screen readers have features to make navigating tables easier. Ensuring ' +
24
+ 'that tables use the actual caption element instead of cells with the `[colspan]` ' +
25
+ 'attribute may improve the experience for screen reader users. ' +
26
+ '[Learn more about captions](https://dequeuniversity.com/rules/axe/4.7/table-fake-caption).',
27
+ };
28
+
29
+ const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
30
+
31
+ class TableFakeCaption extends AxeAudit {
32
+ /**
33
+ * @return {LH.Audit.Meta}
34
+ */
35
+ static get meta() {
36
+ return {
37
+ id: 'table-fake-caption',
38
+ title: str_(UIStrings.title),
39
+ failureTitle: str_(UIStrings.failureTitle),
40
+ description: str_(UIStrings.description),
41
+ requiredArtifacts: ['Accessibility'],
42
+ };
43
+ }
44
+ }
45
+
46
+ export default TableFakeCaption;
47
+ export {UIStrings};
@@ -26,7 +26,8 @@ class TimeToFirstByte extends NavigationMetric {
26
26
 
27
27
  // Estimate when the connection is not warm.
28
28
  // TTFB = DNS + (SSL)? + TCP handshake + 1 RT for request + server response time
29
- let roundTrips = 3;
29
+ let roundTrips = 2;
30
+ if (!mainResource.protocol.startsWith('h3')) roundTrips += 1; // TCP
30
31
  if (mainResource.parsedURL.scheme === 'https') roundTrips += 1;
31
32
  const estimatedTTFB = data.settings.throttling.rttMs * roundTrips + observedResponseTime;
32
33
 
@@ -263,7 +263,9 @@ const defaultConfig = {
263
263
  'accessibility/heading-order',
264
264
  'accessibility/html-has-lang',
265
265
  'accessibility/html-lang-valid',
266
+ 'accessibility/html-xml-lang-mismatch',
266
267
  'accessibility/image-alt',
268
+ 'accessibility/input-button-name',
267
269
  'accessibility/input-image-alt',
268
270
  'accessibility/label',
269
271
  'accessibility/link-name',
@@ -273,6 +275,7 @@ const defaultConfig = {
273
275
  'accessibility/meta-viewport',
274
276
  'accessibility/object-alt',
275
277
  'accessibility/tabindex',
278
+ 'accessibility/table-fake-caption',
276
279
  'accessibility/td-has-header',
277
280
  'accessibility/td-headers-attr',
278
281
  'accessibility/th-has-data-cells',
@@ -528,7 +531,9 @@ const defaultConfig = {
528
531
  {id: 'heading-order', weight: 2, group: 'a11y-navigation'},
529
532
  {id: 'html-has-lang', weight: 3, group: 'a11y-language'},
530
533
  {id: 'html-lang-valid', weight: 3, group: 'a11y-language'},
534
+ {id: 'html-xml-lang-mismatch', weight: 2, group: 'a11y-language'},
531
535
  {id: 'image-alt', weight: 10, group: 'a11y-names-labels'},
536
+ {id: 'input-button-name', weight: 10, group: 'a11y-names-labels'},
532
537
  {id: 'input-image-alt', weight: 10, group: 'a11y-names-labels'},
533
538
  {id: 'label', weight: 10, group: 'a11y-names-labels'},
534
539
  {id: 'link-name', weight: 3, group: 'a11y-names-labels'},
@@ -538,6 +543,7 @@ const defaultConfig = {
538
543
  {id: 'meta-viewport', weight: 10, group: 'a11y-best-practices'},
539
544
  {id: 'object-alt', weight: 3, group: 'a11y-names-labels'},
540
545
  {id: 'tabindex', weight: 3, group: 'a11y-navigation'},
546
+ {id: 'table-fake-caption', weight: 3, group: 'a11y-tables-lists'},
541
547
  {id: 'td-has-header', weight: 10, group: 'a11y-tables-lists'},
542
548
  {id: 'td-headers-attr', weight: 3, group: 'a11y-tables-lists'},
543
549
  {id: 'th-has-data-cells', weight: 3, group: 'a11y-tables-lists'},
@@ -39,34 +39,33 @@ async function runA11yChecks() {
39
39
  resultTypes: ['violations', 'inapplicable'],
40
40
  rules: {
41
41
  // Consider http://go/prcpg for expert review of the aXe rules.
42
- 'tabindex': {enabled: true},
43
42
  'accesskeys': {enabled: true},
44
- 'heading-order': {enabled: true},
45
- 'meta-viewport': {enabled: true},
46
- 'duplicate-id': {enabled: false},
47
- 'table-fake-caption': {enabled: false},
48
- 'td-has-header': {enabled: true},
49
- 'marquee': {enabled: false},
50
43
  'area-alt': {enabled: false},
51
- 'html-xml-lang-mismatch': {enabled: false},
44
+ 'aria-roledescription': {enabled: false},
45
+ 'aria-treeitem-name': {enabled: true},
46
+ 'audio-caption': {enabled: false},
52
47
  'blink': {enabled: false},
53
- 'server-side-image-map': {enabled: false},
48
+ 'duplicate-id': {enabled: false},
49
+ 'frame-focusable-content': {enabled: false},
50
+ 'frame-title-unique': {enabled: false},
51
+ 'heading-order': {enabled: true},
52
+ 'html-xml-lang-mismatch': {enabled: true},
54
53
  'identical-links-same-purpose': {enabled: false},
55
- 'no-autoplay-audio': {enabled: false},
56
- 'svg-img-alt': {enabled: false},
57
- 'audio-caption': {enabled: false},
58
- 'aria-treeitem-name': {enabled: true},
54
+ 'input-button-name': {enabled: true},
55
+ 'link-in-text-block': {enabled: false},
56
+ 'marquee': {enabled: false},
57
+ 'meta-viewport': {enabled: true},
59
58
  // https://github.com/dequelabs/axe-core/issues/2958
60
59
  'nested-interactive': {enabled: false},
61
- 'frame-focusable-content': {enabled: false},
62
- 'aria-roledescription': {enabled: false},
63
- 'scrollable-region-focusable': {enabled: false},
64
- // TODO(paulirish): create audits and enable these 5.
65
- 'input-button-name': {enabled: false},
60
+ 'no-autoplay-audio': {enabled: false},
66
61
  'role-img-alt': {enabled: false},
62
+ 'scrollable-region-focusable': {enabled: false},
67
63
  'select-name': {enabled: false},
68
- 'link-in-text-block': {enabled: false},
69
- 'frame-title-unique': {enabled: false},
64
+ 'server-side-image-map': {enabled: false},
65
+ 'svg-img-alt': {enabled: false},
66
+ 'tabindex': {enabled: true},
67
+ 'table-fake-caption': {enabled: true},
68
+ 'td-has-header': {enabled: true},
70
69
  },
71
70
  });
72
71
 
@@ -194,7 +194,8 @@ class NetworkAnalyzer {
194
194
 
195
195
  // Assume everything before sendStart was just DNS + (SSL)? + TCP handshake
196
196
  // 1 RT for DNS, 1 RT (maybe) for SSL, 1 RT for TCP
197
- let roundTrips = 2;
197
+ let roundTrips = 1;
198
+ if (!record.protocol.startsWith('h3')) roundTrips += 1; // TCP
198
199
  if (record.parsedURL.scheme === 'https') roundTrips += 1;
199
200
  return timing.sendStart / roundTrips;
200
201
  });
@@ -227,8 +228,8 @@ class NetworkAnalyzer {
227
228
  // TTFB = DNS + (SSL)? + TCP handshake + 1 RT for request + server response time
228
229
  if (!connectionReused) {
229
230
  roundTrips += 1; // DNS
231
+ if (!record.protocol.startsWith('h3')) roundTrips += 1; // TCP
230
232
  if (record.parsedURL.scheme === 'https') roundTrips += 1; // SSL
231
- roundTrips += 1; // TCP handshake
232
233
  }
233
234
 
234
235
  // subtract out our estimated server response time
@@ -341,6 +341,7 @@ class NetworkRequest {
341
341
 
342
342
  if (response.protocol) this.protocol = response.protocol;
343
343
 
344
+ // This is updated in _recomputeTimesWithResourceTiming, if timings are present.
344
345
  this.responseHeadersEndTime = timestamp * 1000;
345
346
 
346
347
  this.transferSize = response.encodedDataLength;
@@ -372,16 +373,27 @@ class NetworkRequest {
372
373
  // Don't recompute times if the data is invalid. RequestTime should always be a thread timestamp.
373
374
  // If we don't have receiveHeadersEnd, we really don't have more accurate data.
374
375
  if (timing.requestTime === 0 || timing.receiveHeadersEnd === -1) return;
376
+
375
377
  // Take networkRequestTime and responseHeadersEndTime from timing data for better accuracy.
378
+ // Before this, networkRequestTime and responseHeadersEndTime were set to bogus values based on
379
+ // CDP event timestamps, though they should be somewhat close to the network timings.
380
+ // Note: requests served from cache never run this function, so they use the "bogus" values.
381
+
376
382
  // Timing's requestTime is a baseline in seconds, rest of the numbers there are ticks in millis.
383
+ // See https://raw.githubusercontent.com/GoogleChrome/lighthouse/main/docs/Network-Timings.svg
377
384
  this.networkRequestTime = timing.requestTime * 1000;
378
385
  const headersReceivedTime = this.networkRequestTime + timing.receiveHeadersEnd;
379
- if (!this.responseHeadersEndTime || this.responseHeadersEndTime < 0) {
380
- this.responseHeadersEndTime = headersReceivedTime;
381
- }
382
-
383
- this.responseHeadersEndTime = Math.min(this.responseHeadersEndTime, headersReceivedTime);
386
+ // This was set in `_onResponse` as that event's timestamp.
387
+ const responseTimestamp = this.responseHeadersEndTime;
388
+
389
+ // Update this.responseHeadersEndTime. All timing values from the netstack (timing) are well-ordered, and
390
+ // so are the timestamps from CDP (which this.responseHeadersEndTime belongs to). It shouldn't be possible
391
+ // that this timing from the netstack is greater than the onResponse timestamp, but just to ensure proper order
392
+ // is maintained we bound the new timing by the network request time and the response timestamp.
393
+ this.responseHeadersEndTime = headersReceivedTime;
394
+ this.responseHeadersEndTime = Math.min(this.responseHeadersEndTime, responseTimestamp);
384
395
  this.responseHeadersEndTime = Math.max(this.responseHeadersEndTime, this.networkRequestTime);
396
+
385
397
  // We're only at responseReceived (_onResponse) at this point.
386
398
  // This networkEndTime may be redefined again after onLoading is done.
387
399
  this.networkEndTime = Math.max(this.networkEndTime, this.responseHeadersEndTime);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "lighthouse",
3
3
  "type": "module",
4
- "version": "10.2.0-dev.20230522",
4
+ "version": "10.2.0-dev.20230524",
5
5
  "description": "Automated auditing, performance metrics, and best practices for the web.",
6
6
  "main": "./core/index.js",
7
7
  "bin": {
@@ -272,6 +272,15 @@
272
272
  "core/audits/accessibility/html-lang-valid.js | title": {
273
273
  "message": "`<html>` element has a valid value for its `[lang]` attribute"
274
274
  },
275
+ "core/audits/accessibility/html-xml-lang-mismatch.js | description": {
276
+ "message": "If the webpage does not specify a consistent language, then the screen reader might not announce the page's text correctly. [Learn more about the `lang` attribute](https://dequeuniversity.com/rules/axe/4.7/html-xml-lang-mismatch)."
277
+ },
278
+ "core/audits/accessibility/html-xml-lang-mismatch.js | failureTitle": {
279
+ "message": "`<html>` element does not have an `[xml:lang]` attribute with the same base language as the `[lang]` attribute."
280
+ },
281
+ "core/audits/accessibility/html-xml-lang-mismatch.js | title": {
282
+ "message": "`<html>` element has an `[xml:lang]` attribute with the same base language as the `[lang]` attribute."
283
+ },
275
284
  "core/audits/accessibility/image-alt.js | description": {
276
285
  "message": "Informative elements should aim for short, descriptive alternate text. Decorative elements can be ignored with an empty alt attribute. [Learn more about the `alt` attribute](https://dequeuniversity.com/rules/axe/4.7/image-alt)."
277
286
  },
@@ -281,6 +290,15 @@
281
290
  "core/audits/accessibility/image-alt.js | title": {
282
291
  "message": "Image elements have `[alt]` attributes"
283
292
  },
293
+ "core/audits/accessibility/input-button-name.js | description": {
294
+ "message": "Adding discernable and accessible text to input buttons may help screen reader users understand the purpose of the input button. [Learn more about input buttons](https://dequeuniversity.com/rules/axe/4.7/input-button-name)."
295
+ },
296
+ "core/audits/accessibility/input-button-name.js | failureTitle": {
297
+ "message": "Input buttons do not have discernible text."
298
+ },
299
+ "core/audits/accessibility/input-button-name.js | title": {
300
+ "message": "Input buttons have discernible text."
301
+ },
284
302
  "core/audits/accessibility/input-image-alt.js | description": {
285
303
  "message": "When an image is being used as an `<input>` button, providing alternative text can help screen reader users understand the purpose of the button. [Learn about input image alt text](https://dequeuniversity.com/rules/axe/4.7/input-image-alt)."
286
304
  },
@@ -362,6 +380,15 @@
362
380
  "core/audits/accessibility/tabindex.js | title": {
363
381
  "message": "No element has a `[tabindex]` value greater than 0"
364
382
  },
383
+ "core/audits/accessibility/table-fake-caption.js | description": {
384
+ "message": "Screen readers have features to make navigating tables easier. Ensuring that tables use the actual caption element instead of cells with the `[colspan]` attribute may improve the experience for screen reader users. [Learn more about captions](https://dequeuniversity.com/rules/axe/4.7/table-fake-caption)."
385
+ },
386
+ "core/audits/accessibility/table-fake-caption.js | failureTitle": {
387
+ "message": "Tables do not use `<caption>` instead of cells with the `[colspan]` attribute to indicate a caption."
388
+ },
389
+ "core/audits/accessibility/table-fake-caption.js | title": {
390
+ "message": "Tables use `<caption>` instead of cells with the `[colspan]` attribute to indicate a caption."
391
+ },
365
392
  "core/audits/accessibility/td-has-header.js | description": {
366
393
  "message": "Screen readers have features to make navigating tables easier. Ensuring that `<td>` elements in a large table (3 or more cells in width and height) have an associated table header may improve the experience for screen reader users. [Learn more about table headers](https://dequeuniversity.com/rules/axe/4.7/td-has-header)."
367
394
  },
@@ -272,6 +272,15 @@
272
272
  "core/audits/accessibility/html-lang-valid.js | title": {
273
273
  "message": "`<html>` êĺêḿêńt̂ h́âś â v́âĺîd́ v̂ál̂úê f́ôŕ ît́ŝ `[lang]` át̂t́r̂íb̂út̂é"
274
274
  },
275
+ "core/audits/accessibility/html-xml-lang-mismatch.js | description": {
276
+ "message": "Îf́ t̂h́ê ẃêb́p̂áĝé d̂óêś n̂ót̂ śp̂éĉíf̂ý â ćôńŝíŝt́êńt̂ ĺâńĝúâǵê, t́ĥén̂ t́ĥé ŝćr̂éêń r̂éâd́êŕ m̂íĝh́t̂ ńôt́ âńn̂óûńĉé t̂h́ê ṕâǵê'ś t̂éx̂t́ ĉór̂ŕêćt̂ĺŷ. [Ĺêár̂ń m̂ór̂é âb́ôút̂ t́ĥé `lang` ât́t̂ŕîb́ût́ê](https://dequeuniversity.com/rules/axe/4.7/html-xml-lang-mismatch)."
277
+ },
278
+ "core/audits/accessibility/html-xml-lang-mismatch.js | failureTitle": {
279
+ "message": "`<html>` êĺêḿêńt̂ d́ôéŝ ńôt́ ĥáv̂é âń `[xml:lang]` ât́t̂ŕîb́ût́ê ẃît́ĥ t́ĥé ŝám̂é b̂áŝé l̂án̂ǵûáĝé âś t̂h́ê `[lang]` át̂t́r̂íb̂út̂é."
280
+ },
281
+ "core/audits/accessibility/html-xml-lang-mismatch.js | title": {
282
+ "message": "`<html>` êĺêḿêńt̂ h́âś âń `[xml:lang]` ât́t̂ŕîb́ût́ê ẃît́ĥ t́ĥé ŝám̂é b̂áŝé l̂án̂ǵûáĝé âś t̂h́ê `[lang]` át̂t́r̂íb̂út̂é."
283
+ },
275
284
  "core/audits/accessibility/image-alt.js | description": {
276
285
  "message": "Îńf̂ór̂ḿât́îv́ê él̂ém̂én̂t́ŝ śĥóûĺd̂ áîḿ f̂ór̂ śĥór̂t́, d̂éŝćr̂íp̂t́îv́ê ál̂t́êŕn̂át̂é t̂éx̂t́. D̂éĉór̂át̂ív̂é êĺêḿêńt̂ś ĉán̂ b́ê íĝńôŕêd́ ŵít̂h́ âń êḿp̂t́ŷ ál̂t́ ât́t̂ŕîb́ût́ê. [Ĺêár̂ń m̂ór̂é âb́ôút̂ t́ĥé `alt` ât́t̂ŕîb́ût́ê](https://dequeuniversity.com/rules/axe/4.7/image-alt)."
277
286
  },
@@ -281,6 +290,15 @@
281
290
  "core/audits/accessibility/image-alt.js | title": {
282
291
  "message": "Îḿâǵê él̂ém̂én̂t́ŝ h́âv́ê `[alt]` át̂t́r̂íb̂út̂éŝ"
283
292
  },
293
+ "core/audits/accessibility/input-button-name.js | description": {
294
+ "message": "Âd́d̂ín̂ǵ d̂íŝćêŕn̂áb̂ĺê án̂d́ âćĉéŝśîb́l̂é t̂éx̂t́ t̂ó îńp̂út̂ b́ût́t̂ón̂ś m̂áŷ h́êĺp̂ śĉŕêén̂ ŕêád̂ér̂ úŝér̂ś ûńd̂ér̂śt̂án̂d́ t̂h́ê ṕûŕp̂óŝé ôf́ t̂h́ê ín̂ṕût́ b̂út̂t́ôń. [L̂éâŕn̂ ḿôŕê áb̂óût́ îńp̂út̂ b́ût́t̂ón̂ś](https://dequeuniversity.com/rules/axe/4.7/input-button-name)."
295
+ },
296
+ "core/audits/accessibility/input-button-name.js | failureTitle": {
297
+ "message": "Îńp̂út̂ b́ût́t̂ón̂ś d̂ó n̂ót̂ h́âv́ê d́îśĉér̂ńîb́l̂é t̂éx̂t́."
298
+ },
299
+ "core/audits/accessibility/input-button-name.js | title": {
300
+ "message": "Îńp̂út̂ b́ût́t̂ón̂ś ĥáv̂é d̂íŝćêŕn̂íb̂ĺê t́êx́t̂."
301
+ },
284
302
  "core/audits/accessibility/input-image-alt.js | description": {
285
303
  "message": "Ŵh́êń âń îḿâǵê íŝ b́êín̂ǵ ûśêd́ âś âń `<input>` b̂út̂t́ôń, p̂ŕôv́îd́îńĝ ál̂t́êŕn̂át̂ív̂é t̂éx̂t́ ĉán̂ h́êĺp̂ śĉŕêén̂ ŕêád̂ér̂ úŝér̂ś ûńd̂ér̂śt̂án̂d́ t̂h́ê ṕûŕp̂óŝé ôf́ t̂h́ê b́ût́t̂ón̂. [Ĺêár̂ń âb́ôút̂ ín̂ṕût́ îḿâǵê ál̂t́ t̂éx̂t́](https://dequeuniversity.com/rules/axe/4.7/input-image-alt)."
286
304
  },
@@ -362,6 +380,15 @@
362
380
  "core/audits/accessibility/tabindex.js | title": {
363
381
  "message": "N̂ó êĺêḿêńt̂ h́âś â `[tabindex]` v́âĺûé ĝŕêát̂ér̂ t́ĥán̂ 0"
364
382
  },
383
+ "core/audits/accessibility/table-fake-caption.js | description": {
384
+ "message": "Ŝćr̂éêń r̂éâd́êŕŝ h́âv́ê f́êát̂úr̂éŝ t́ô ḿâḱê ńâv́îǵât́îńĝ t́âb́l̂éŝ éâśîér̂. Én̂śûŕîńĝ t́ĥát̂ t́âb́l̂éŝ úŝé t̂h́ê áĉt́ûál̂ ćâṕt̂íôń êĺêḿêńt̂ ín̂śt̂éâd́ ôf́ ĉél̂ĺŝ ẃît́ĥ t́ĥé `[colspan]` ât́t̂ŕîb́ût́ê ḿâý îḿp̂ŕôv́ê t́ĥé êx́p̂ér̂íêńĉé f̂ór̂ śĉŕêén̂ ŕêád̂ér̂ úŝér̂ś. [L̂éâŕn̂ ḿôŕê áb̂óût́ ĉáp̂t́îón̂ś](https://dequeuniversity.com/rules/axe/4.7/table-fake-caption)."
385
+ },
386
+ "core/audits/accessibility/table-fake-caption.js | failureTitle": {
387
+ "message": "T̂áb̂ĺêś d̂ó n̂ót̂ úŝé `<caption>` îńŝt́êád̂ óf̂ ćêĺl̂ś ŵít̂h́ t̂h́ê `[colspan]` át̂t́r̂íb̂út̂é t̂ó îńd̂íĉát̂é â ćâṕt̂íôń."
388
+ },
389
+ "core/audits/accessibility/table-fake-caption.js | title": {
390
+ "message": "T̂áb̂ĺêś ûśê `<caption>` ín̂śt̂éâd́ ôf́ ĉél̂ĺŝ ẃît́ĥ t́ĥé `[colspan]` ât́t̂ŕîb́ût́ê t́ô ín̂d́îćât́ê á ĉáp̂t́îón̂."
391
+ },
365
392
  "core/audits/accessibility/td-has-header.js | description": {
366
393
  "message": "Ŝćr̂éêń r̂éâd́êŕŝ h́âv́ê f́êát̂úr̂éŝ t́ô ḿâḱê ńâv́îǵât́îńĝ t́âb́l̂éŝ éâśîér̂. Én̂śûŕîńĝ t́ĥát̂ `<td>` él̂ém̂én̂t́ŝ ín̂ á l̂ár̂ǵê t́âb́l̂é (3 ôŕ m̂ór̂é ĉél̂ĺŝ ín̂ ẃîd́t̂h́ âńd̂ h́êíĝh́t̂) h́âv́ê án̂ áŝśôćîát̂éd̂ t́âb́l̂é ĥéâd́êŕ m̂áŷ ím̂ṕr̂óv̂é t̂h́ê éx̂ṕêŕîén̂ćê f́ôŕ ŝćr̂éêń r̂éâd́êŕ ûśêŕŝ. [Ĺêár̂ń m̂ór̂é âb́ôút̂ t́âb́l̂é ĥéâd́êŕŝ](https://dequeuniversity.com/rules/axe/4.7/td-has-header)."
367
394
  },