Skip to content

feat: add source_language config and lang attr for untranslated text - #14429

Open
hesam-oxe wants to merge 5 commits into
sphinx-doc:masterfrom
hesam-oxe:feat/source-language-lang-attr
Open

hesam-oxe wants to merge 5 commits into
sphinx-doc:masterfrom
hesam-oxe:feat/source-language-lang-attr

Conversation

@hesam-oxe

Copy link
Copy Markdown

Added source_language config option and lang attribute on
untranslated nodes for WCAG SC 3.1.2 compliance.

Problem

When working with mixed-language web content, HTML elements should use
the lang attribute to define their language if it differs from the
<html> page language. Without this, documentation produced with Sphinx
fails WCAG SC 3.1.2 Language of Parts.

Changes

  • config.py — Added source_language config option (default: "en")
  • transforms/i18n.py — Set node['lang'] to source_language on
    untranslated nodes in AddTranslationClasses
  • writers/html5.py — Override starttag() in HTML5Translator to
    respect node lang attribute

Result

Before:

<p class="untranslated">This is in English.</p>

After:

<p lang="en" class="untranslated">This is in English.</p>

References

  • WCAG SC 3.1.2 Language of Parts
  • Discussion at PyCon UK with @AA-Turner
  • Python forum: Accessibility of multilingual content

Closes #13841

@jdillard jdillard added the type:enhancement enhance or introduce a new feature label Jul 31, 2026
@hesam-oxe

Copy link
Copy Markdown
Author

Fixed the CI failures — ready for re-review! 🙏

The starttag override was accidentally a module-level function instead of an HTML5Translator method (bare super() + missing return), which is what ruff/mypy/pyright/ty were flagging. It is now a proper method override matching the docutils signature, always delegating to super().starttag(). Also dropped a redundant condition in i18n.py.

Verified locally: ruff clean on all touched lines, plus test_intl (61), test_build_html and test_config (123) all pass.

@hesam-oxe
hesam-oxe force-pushed the feat/source-language-lang-attr branch from 759f33c to f1a0270 Compare September 18, 2026 04:19
@hesam-oxe

Copy link
Copy Markdown
Author

I have rebased this PR onto the latest master and added test coverage and documentation:

What was done

  1. Rebase onto current master — the branch was previously based on 9.1.0 final; it now includes all upstream fixes up to e44a40eb.
  2. CI repair — the 6 failing tests (test_viewcode, test_viewcode_linenos, test_default_highlight, test_html_code_role, test_additional_targets_*) were caused by Pygments 2.21.0 changing its quote-escaping behaviour (&quot; → "), not by this feature — I verified they fail identically on plain master. I cherry-picked the test-expectation updates from Update Pygments expectations and stabilize build tests #14674 so the suite passes with both old and new Pygments.
  3. New test — test_source_language_lang_attr in tests/test_intl/test_intl.py: asserts that untranslated elements carry lang="en" (doctree-level and in the rendered HTML) and translated ones do not, using translation_progress_classes: untranslated.
  4. Documentation — source_language confval documented in doc/usage/configuration.rst with a versionadded:: 9.2 marker, and a CHANGES.rst entry.

All 195 related tests pass locally (Python 3.12, docutils 0.22, Pygments 2.21). Happy to adjust anything — in particular, let me know if you would prefer the Pygments test fix to be dropped from this PR once #14674 merges.

@hesam-oxe

Copy link
Copy Markdown
Author

Follow-up on the new head: the ruff job failure was mine — the new test in tests/test_intl/test_intl.py was not in ruff format style. Fixed in b02ea09 (ruff format clean, ruff check still passing).

For completeness, the remaining red jobs on this branch are pre-existing and unrelated:

@hesam-oxe

Copy link
Copy Markdown
Author

Follow-up on the new head: the ruff job failure was mine — the new test in tests/test_intl/test_intl.py was not in ruff format style. Fixed in b02ea09 (ruff format clean, ruff check still passing).

For completeness, the remaining red jobs on this branch are pre-existing and unrelated:

hesam-oxe and others added 4 commits September 19, 2026 06:29
Added source_language config option. Set lang attribute on untranslated nodes for WCAG 3.1.2 compliance. Closes sphinx-doc#13841
The starttag override was accidentally defined as a module-level
function (where bare super() is illegal and the implicit-missing
return broke the str contract), so ruff/mypy/pyright/ty all flagged
it. Move it into HTML5Translator with the docutils signature
(node, tagname, suffix, empty, **atts) and always delegate to
super().starttag(). Also drop a redundant condition in i18n.py
(already inside the untranslated else-branch).
- tests/test_intl: test_source_language_lang_attr — asserts the lang
  attribute lands on untranslated elements (doctree + HTML output)
- doc/usage/configuration.rst: document the new source_language confval
- CHANGES.rst: add the entry under 9.1.1 Features added
@hesam-oxe
hesam-oxe force-pushed the feat/source-language-lang-attr branch from b02ea09 to 19107bc Compare September 19, 2026 06:35
@hesam-oxe

Copy link
Copy Markdown
Author

Rebased on current master, conflicts resolved. The redundant Pygments-expectation cherry-pick is dropped (upstream #14611 now covers it); kept the source_language feature, test_source_language_lang_attr, docs, and CHANGES entry. ruff format clean on touched files. Note: Docutils-HEAD and LaTeX CI failures are pre-existing (#14673), not related to this change.

@saitanallensantiago26-beep

Copy link
Copy Markdown

Added source_language config option and lang attribute on
untranslated nodes for WCAG SC 3.1.2 compliance.

Problem

When working with mixed-language web content, HTML elements should use
the lang attribute to define their language if it differs from the
<html> page language. Without this, documentation produced with Sphinx
fails WCAG SC 3.1.2 Language of Parts.

Changes

  • config.py — Added source_language config option (default: "en")
  • transforms/i18n.py — Set node['lang'] to source_language on
    untranslated nodes in AddTranslationClasses
  • writers/html5.py — Override starttag() in HTML5Translator to
    respect node lang attribute

Result

Before:

<p class="untranslated">This is in English.</p>

After:

<p lang="en" class="untranslated">This is in English.</p>

References

  • WCAG SC 3.1.2 Language of Parts
  • Discussion at PyCon UK with @AA-Turner
  • Python forum: Accessibility of multilingual content

Closes #13841

@hesam-oxe

Copy link
Copy Markdown
Author

Rebased on current master. Verified: Docutils-HEAD and LaTeX failures are pre-existing (#14673) — same TypeError signature on clean master without my changes. The Python 3.12 (Docutils 0.21) run shows 1 unrelated failure (test_numfig_disabled_warn, numfig warning assertion — not i18n/lang); touched test test_source_language_lang_attr passes locally, ruff format clean, ruff check shows only pre-existing noqa-style findings outside this diff.

@hesam-oxe

Copy link
Copy Markdown
Author

Thank you for the patience on CI.

Update on head a1f6b36 (retrigger):

I pushed an empty commit to retrigger CI after the earlier LaTeX failure. Happy to address any concerns on the source_language + lang attribute implementation for WCAG SC 3.1.2.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:enhancement enhance or introduce a new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

lang attribute set to source language for untranslated text

3 participants