Problem/Motivation

When embedding media via Media oEmbed on multilingual Drupal sites, the sandboxed iframe page (/[langcode]/media/oembed?...) renders without a lang attribute on its element. Without this attribute, assistive technologies cannot determine the language of the page and may apply the wrong speech engine.

This triggers accessibility audit failures referencing WCAG SC 3.1.1 Language of Page (Level A).

Steps to reproduce

  1. Set up a multilingual Drupal site (e.g. English + French).
  2. Install the Media module.
  3. Create content with an embedded YouTube video via the Media module (Remote video / oEmbed).
  4. Visit the content page in a non-default language (e.g. /fr/...).
  5. Open the oEmbed sandboxed page directly (/fr/media/oembed?...). In Edge, you can get the URL by inspecting iframe element on the node page with DevTools and finding the #document element within. Right-click the URL for #document and choose "Open in new tab".
  6. Inspect the <html> tag: no lang attribute is present.
  7. Run an accessibility audit: a missing lang attribute error is reported on the oEmbed page.

Current behavior

media-oembed-iframe.html.twig renders:

<html>
  <head>...</head>
  <body>
    <iframe src="https://www.youtube.com/embed/ID?feature=oembed"></iframe>
  </body>
</html>

The template renders with no lang attribute.

Expected behavior

The template should render (or the appropriate language code for the current content language).

Proposed solution

Add a preprocess_media_oembed_iframe hook that reads the current content language and passes it as langcode to the template. Apply it via lang="{{ langcode }}" on the element.

Additional notes

  • The media-oembed-iframe.html.twig template does not set a lang attribute on at all, which is also an issue independently of YouTube: any text inside the oEmbed page is language-less from an assistive technology perspective.
  • This issue is related to but distinct from #3085545 (inner iframe missing title attribute) and #3152111 (duplicate iframe titles).
  • The outer Drupal iframe (rendered by OEmbedFormatter) also has no lang attribute, though fixing the oEmbed page itself seems more impactful.
  • Tested on Drupal 11.3.8, confirmed on a production multilingual site.

Issue fork drupal-3593533

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

gwenweb created an issue. See original summary.

gwenweb’s picture

Issue summary: View changes

quietone’s picture

Version: 11.x-dev » main

Hi, Issues for Drupal core should be targeted to the 'main' branch, our primary development branch. Changes are made on the main branch first, and are then back ported as needed according to the Core change policies. This is also mentioned on the version section of the list of issue fields documentation. The version the problem was discovered on should be stated in the issue summary Problem/Motivation section. Thanks.

gwenweb’s picture

Issue summary: View changes
gwenweb’s picture

Thank you for the guidance! I've updated the Issue Summary to mention that the problem was discovered on Drupal 11.x.

I also noticed the MR was incorrectly based (the branch included all of Drupal core's files instead of just the fix). I've rebased it properly — the MR now contains a single commit with only 2 files changed:

  • core/modules/media/src/Hook/MediaThemeHooks.php — declares the langcode variable and adds a preprocess hook
  • core/modules/media/templates/media-oembed-iframe.html.twig — applies lang="{{ langcode }}" on the element

Apologies for the noise, and happy to adjust anything further.

kentr’s picture

Status: Active » Postponed (maintainer needs more info)

Thanks for reporting this.

I have a question about the expected result.

In Microsoft Edge / macOS with the MR, I see <html lang="fr"> in the page source, but the video UI is still in English. For example, the tooltip that appears when hovering the pointer over the Play button says "Play video".

When I add French as a language and put it at the top of the list in the browser settings, the video UI is in French (I think it's French :-).

And the video UI stays in French when I go back to the English version of the page.

So, it seems that the new lang attribute has no effect on what YouTube serves.

It also concerns me that the actual content served by YouTube can be in a different language than what the lang specifies. Doesn't that still fail SC 3.1.2 Language of Parts (Level AA) (and maybe also SC 3.1.1 Language of Page (Level A), since this is a self-contained document inside the iframe)?

Edit: Is it expected that the served media will actually be in the language specified by the lang attribute?

kentr’s picture

Issue summary: View changes
Issue tags: +wcag312

I added to the steps to reproduce, formatted the IS a little, and tagged for SC 3.1.2.

gwenweb’s picture

Thank you for testing this so thoroughly, kentr — and for the very precise question.

To be honest: no, I did not expect the lang attribute alone to change what YouTube serves. The lang attribute on tells assistive technologies (screen readers) what language this Drupal-generated wrapper page is in, so they can apply the correct speech engine. It has no effect on YouTube's player UI, which is driven by the hl URL parameter, the user's browser locale, or their Google account settings.

So this MR only addresses WCAG SC 3.1.1 (Language of Page) — not SC 3.1.2. You're right that SC 3.1.2 would require passing hl to the YouTube embed URL, which is a separate and more complex change.

I may have caused confusion by mentioning SC 3.1.2 in the issue summary. Would it make sense to narrow this issue to SC 3.1.1 only, and open a separate issue for the hl parameter? I'm happy to update the summary accordingly.

kentr’s picture

Status: Postponed (maintainer needs more info) » Needs review
Issue tags: -wcag312 +Needs issue summary update

@gwenweb

So this MR only addresses WCAG SC 3.1.1 (Language of Page) — not SC 3.1.2. You're right that SC 3.1.2 would require passing hl to the YouTube embed URL, which is a separate and more complex change.

I may have caused confusion by mentioning SC 3.1.2 in the issue summary. Would it make sense to narrow this issue to SC 3.1.1 only, and open a separate issue for the hl parameter? I'm happy to update the summary accordingly.

Sounds good to me. I got an error from Accessibility Insights about the missing lang attribute on the sandboxed page.

After you update the issue summary, I want to get signoff from another accessibility team member.

kentr’s picture

Status: Needs review » Needs work

I meant to put this to Needs work, not Needs review.

gwenweb’s picture

Issue summary: View changes
kentr’s picture

Title: oEmbed iframe page has no lang attribute on <html>, and does not pass current page language to embedded players (e.g. YouTube hl parameter) » oEmbed iframe page has no lang attribute on <html>
Issue tags: -Needs issue summary update +Needs accessibility review

Thanks @gwenweb.

So, I found this Accessibility Conformance Testing (ACT) rule which leads me to believe that it's not technically a failure of SC 3.1.1. However, it says in the last sentence that it still may be a problem.

This rule applies to any document element if it is an html element for which all the following are true:

Note: html elements within iframe and object elements are not applicable as iframe and object elements create nested browsing contexts. However, as these elements are meant to provide a layer of isolation, the declared language of their parent browsing context will likely not be inherited, making it possible for empty lang attributes in nested browsing contexts to also cause accessibility issues.

I narrowed the issue title to apply only to the html attribute.

kentr’s picture

I added to the quote in my previous comment.

kentr’s picture

Note: That link / quote is from the Accessibility Conformance Testing (ACT) rule to test 3.1.1: Language of Page (Level A).

That would explain why Accessibility Insights doesn't throw an error for the main page: the html in question is not the top-level browsing context.

@gwenweb, was this from a manual audit? I'm curious to hear the auditors' thoughts on the ACT rule.

kentr’s picture

BTW, my noting that this may not technically be a failure of SC 3.1.1 was not a statement that the change shouldn't still be made.

gwenweb’s picture

Thank you for asking !

The audit was conducted by https://accessibility.belgium.be/, the Belgian federal authority for digital accessibility. Their finding was:

"The language of the

element does not match the language of the current page. The lang attribute value of the YouTube player does not follow the language of the current page. [...] This can be modified via the YouTube IFrame Player API settings (parameter: hl)." If I'm reading this correctly, their report seems to be about the YouTube player language (the hl parameter) — which would be closer to the SC 3.1.2 concern you already identified. But I may be misinterpreting what they flagged exactly. As for the ACT rule, I honestly hadn't considered that angle. If the sandboxed page doesn't technically fall under SC 3.1.1 because of its nested browsing context, then I'm not sure what the right framing for this fix is — maybe just a best-practice improvement rather than a strict WCAG fix? I still need to open the follow-up issue for the hl parameter — I'll do that once this one moves forward.
kentr’s picture

"The language of the element does not match the language of the current page. The lang attribute value of the YouTube player does not follow the language of the current page. [...] This can be modified via the YouTube IFrame Player API settings (parameter: hl)."

Yeah, that sounds like it's specifically related to the player itself (the HTML served by YouTube that constitutes the player).

What's interesting is that I can create a media item in Drupal with &hl=fr in the URL, and YouTube still gives me an English version until I change the browser language preferences.

gwenweb’s picture

That's a really interesting finding — if &hl=fr doesn't reliably change the player language and YouTube ultimately defers to the browser preference, then the SC 3.1.2 fix may be less straightforward than it seemed.

I'll leave it to the accessibility team to decide whether this MR still makes sense as a standalone fix for the wrapper page.