dashorst opened a new issue, #1848: URL: https://github.com/apache/wicket/issues/1848
A page rendered by Wicket has no `lang` attribute on its `<html>` element unless the developer writes one in the markup or binds a component to the tag. WCAG 2.2 success criterion 3.1.1 (level A) requires the language of every page to be determinable by software: screen readers pick their pronunciation from it, browsers their hyphenation and translation offers. Wicket knows the language the page is rendered in, `Component#getLocale()`, but does nothing with it. A `lang` written in the markup is wrong as soon as the application is localized, because the strings on the page follow the session locale and the markup file does not. The workaround the user guide shows (#1839) binds the tag to a component: ```html <html wicket:id="html" xmlns:wicket="http://wicket.apache.org"> ``` ```java TransparentWebMarkupContainer html = new TransparentWebMarkupContainer("html"); html.add(AttributeModifier.replace("lang", () -> getLocale().toLanguageTag())); add(html); ``` It works, but every application has to know about it, every page carries an extra container and behavior, and the container being transparent is easy to get wrong. ## Rewriting the tag while parsing does not work A markup filter that adds `lang` to the raw `<html>` tag gets the locale from the `ContainerInfo` of the markup resource stream, but `MarkupCache` stores the parsed markup by the location of the file, not by locale. The locale-specific cache key only maps to that location, so every locale shares the markup parsed for whichever locale loaded the file first. A prototype rendered `lang="nl-NL"` for a German session after a Dutch one. The language has to be added when the page renders. ## Proposal 1. When the markup of a page is parsed, the top-level `<html>` tag without a `wicket:id` is kept as a tag, with a flag and a reserved id, instead of being merged into raw markup, much like `HtmlHeaderSectionHandler` does for `<head>`, but without resolving a component for it. 2. When `MarkupContainer#renderNext` meets the flagged tag, it takes a mutable copy, lets the page modify it, and writes it, the way it already writes a tag flagged `RENDER_RAW` without a component. No component is created and nothing is stored in the page. 3. The page hook, for instance `WebPage#onHtmlTag(ComponentTag)`, sets `lang` to `getLocale().toLanguageTag()` when the markup has no `lang` and the locale has a language. After the hook the application's `IOnComponentTagListener`s are called with the page and the tag, so an application can add `dir`, a class or other attributes with the API it already uses for component tags. A `lang` written in the markup is kept, because a page may be written in one language whatever the session locale. A `<html wicket:id="...">` bound to a component is left to that component, so the workaround above keeps working. The `<html>` in panel, border and fragment markup is never rendered and is not affected; with markup inheritance only the `<html>` of the base page is. ## Open questions - Should core also render `dir="rtl"` for right-to-left languages? `java.awt.ComponentOrientation` knows them but lives in `java.desktop`, so core would need its own list (ar, he, fa, ur and a few more). - Is a setting needed to switch the attribute off, or is overriding the page hook enough? - Pages without `lang` render different markup after this change. Applications that compare rendered pages with expected files, as `wicket-core-tests` does, have to update those files. The migration guide should mention it. ## Context Found while writing the accessibility chapter of the user guide (#1839); it is one of the gaps for the component audit in #1838. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
