Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 180 additions & 0 deletions _rules/element-lang-programmatically-determinable-7ed469.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
---
id: 7ed469
name: Element language is programmatically determinable
rule_type: atomic
description: |
This rule checks that the language of an element in the page body can be programmatically determined.
accessibility_requirements: # Remove whatever is not applicable
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the rule is also mapping to 3.1.1: if an element has no ancestor with a valid lang, then the document element has no valid lang.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i understood accessibility_requirements as the list of (in this case) WCAG SCs that this is used to test conformance to. as this rule is scoped to descendants of body, it cannot be used to test 3.1.1 language of the page itself, as that needs to (in HTML) be defined for the html element?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that the rule is not designed to test SC 3.1.1, but it still does test a bit of it indirectly…
As always, we focus on the fail-on-fail relationship. A failure of this rule indicates a failure of SC 3.1.1 (in addition to 3.1.2). A Pass on this rule does not indicate a Pass of 3.1.1, but neither of 3.1.2… That's how it is for most rules.

Then, it is true also that a failure of this rule implies a failure of HTML page has lang attribute, and that is why it fails 3.1.1. That's also OK. This rule checks more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wondering now if another failure purely for this rule (which i've not added here, but can if it's deemed an actual failure) would be something like

<html lang="en">
  <body>
    <div lang="foo">
      <p>Content</p>
    </div>
  </body>
</html>

where the p fails because its ancestor div has an invalid language attribute, but the page itself does pass 3.1.1...and so a failure of this rule does not indicate a failure of 3.1.1

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rule currently does not fail that because "any of its [the p] ancestor" has a valid lang tag.
I agree that this is a failure of 3.1.2 but not of 3.1.1

I see 2 possibilities:
=> Change the rule to "its closest ancestor with a lang attribute" or something similar. This makes the rule more tricky. In this case, it would indeed not map to 3.1.1
=> Leave the rule as is. This keeps the rule simpler and more focused. This case is already handled by Element within body has valid lang attribute, so there is no real need to enforce it in this rule. The main "problem" with this solution is that Passed Examples must pass the SC, so we cannot use this as a Passed Example to illustrate the limitation of the rule. This is not really a big deal…

Given that this case is already handle by anther rule, I'd rather keep this rule simple.

wcag20:3.1.2: # Language of Parts (AA)
forConformance: true
failed: not satisfied
passed: further testing is needed
inapplicable: further testing is needed
input_aspects:
- DOM Tree
- CSS Styling

acknowledgements:
authors:
- Patrick H. Lauke
---

## Applicability

This rules applies to any HTML element that:

* contains a [text node](https://dom.spec.whatwg.org/#text) as a [child](https://dom.spec.whatwg.org/#concept-tree-child) element
* is a [descendant](https://dom.spec.whatwg.org/#concept-tree-descendant) in the [flat tree](https://drafts.csswg.org/css-scoping/#flat-tree) of a `body` element
* is [included in the accessibility tree][]

## Expectation (1)

For each test target, the test target itself or any of its [ancestor](https://dom.spec.whatwg.org/#concept-tree-ancestor) elements (up to and including the root element of the document) in the [flat tree](https://drafts.csswg.org/css-scoping/#flat-tree) has a `lang` attribute with a valid language subtag.

## Assumptions

_There are currently no assumptions_

## Accessibility Support

_There are no major accessibility support issues known for this rule._

## Background

In practice, this rule will be satisfied if the separate success criterion [3.1.1 Language of Page (Level: A)](https://www.w3.org/TR/WCAG21/#language-of-page) is satisfied. This rule ensures that if 3.1.1 is *not* satisfied, content is checked for alternative ways in which language of page content itself can still have a programmatically determinable human language.

- [CSS Scoping Module Level 1 (editor's draft)](https://drafts.csswg.org/css-scoping/)
- [Understanding Success Criterion 3.1.2: Language of Parts](https://www.w3.org/WAI/WCAG21/Understanding/language-of-parts.html)

## Test Cases

### Passed

#### Passed Example 1

The language of the `p` element is inherited by the `lang` attribute on the `html` root element.

```html
<html lang="en">
<body>
<p>Content</p>
</body>
</html>
```

#### Passed Example 2

The language of the `p` element is inherited by the `lang` attribute on the `div` parent element. Note that this example fails 3.1.1 Language of Page (Level: A) as the `html` root element lacks a `lang` attribute.

```html
<html>
<body>
<div lang="en">
<p>Content</p>
</div>
</body>
</html>
```

#### Passed Example 3

The language of the `p` element is inherited by the `lang` attribute on the `div` ancestor element. Note that this example fails 3.1.1 Language of Page (Level: A) as the `html` root element lacks a `lang` attribute.

```html
<html>
<body>
<div lang="en">
<div>
<p>Content</p>
</div>
</div>
</body>
</html>
```
Comment on lines +65 to +93
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two examples are actually pretty much the same (the lang attribute is on an ancestor which is not the html element). You can remove one of them.

OTOH, I think it would be good to add an example to illustrate the "child text node" part of the rule.

<body>
<div>
<p lang="en">Hello</p>
</div>
</body>

The p is good. The div is inapplicable. So this passes the rule.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change the rule to "its closest ancestor with a lang attribute" or something similar

I think I'm actually tending towards this one, as the closest ancestor is indeed what plays the major part in the essence of this rule, as it relates more closely in how the language of the specific element itself is calculated/programmatically determined.

And mainly, because I do think there's value in making sure that it's clear that there can be failures of this rule that fail 3.1.2 but not 3.1.1.

Copy link
Contributor Author

@patrickhlauke patrickhlauke Nov 22, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two examples are actually pretty much the same

ah, good spot. wanted to make the difference between parent and ancestor clear (or rather, that we're not just talking about parent), but probably no need to do two examples that are so close to each other. will go with ancestor one, as parent is just a special case of ancestor

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that you can also go even simpler:
check the existence of a lang attribute, not its validity. Then you can go for any ancestor without problem, the rule is much simpler and keep a single concern (it does not need to know what are valid/invalid language tags). Given that we already have rules that check validity of language tags, this is not going to be a real problem.

The point here being that we don't need the rule to be completely covering a single SC. It is better (imho) to have simple rules checking a simple thing and use a combination of rules to cover a SC (rules are already complicated beast, keeping them simple helps writers, readers and testers; simpler rules are also better for separation of concern).

This is a personal opinion and mostly showing what can be done. Of course, go the direction you want 😄 given that you are the one doing the job in the first place…

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'll mull it over. appreciate the thorough discussion on this, particularly as i dove in on the deep end here :)


### Failed

#### Failed Example 1

The language of the `p` element cannot be programmatically determined as the element itself and none of its ancestors, including the `html` root element, has a defined `lang` attribute.

```html
<html>
<body>
<p>Content</p>
</body>
</html>
```

#### Failed Example 2

The language of the `p` element with `id` attribute `ko` cannot be programmatically determined as the element itself and none of its ancestors, including the `html` root element, has a defined `lang` attribute.

```html
<html>
<body>
<div lang="en">
<div>
<p id="ok">Content</p>
</div>
</div>
<div>
<p id="ko">Content</p>
</div>
</body>
</html>
```

#### Failed Example 3

The language of the `p` element is inherited by the `lang` attribute on the `div` ancestor element, but the value of this `lang` attribute is not a valid language subtag.

```html
<html>
<body>
<div lang="foo">
<div>
<p>Content</p>
</div>
</div>
</body>
</html>
```

### Inapplicable

#### Inapplicable Example 1

While the language of the `p` element cannot be programmatically determined, as the element itself and none of its ancestors has a defined `lang` attribute, the `p` element contains no actual text content.

```html
<html>
<body>
<p></p>
</body>
</html>
```

#### Inapplicable Example 2

While the language of the `p` element cannot be programmatically determined, as the element itself and none of its ancestors has a defined `lang` attribute, the `p` element is not part of the accessibilty tree.

```html
<html>
<body>
<p aria-hidden="true">Content</p>
</body>
</html>
```

#### Inapplicable Example 2

The `body` element has no descendants.

```html
<html>
<body></body>
</html>
```

[included in the accessibility tree]: #included-in-the-accessibility-tree 'Definition of included in the accessibility tree'