Proposal: let's reduce customization and use Sphinx's standard wording for version annotations

I’m working through @medmunds PRs around improving everything related to Django docs building process and ability to switch themes. This work starts with cleaning up our custom docs/_ext/djangodocs.py Sphinx extension, and in this stage we could simplify greatly this file if we switch the version annotations wording to what Sphinx provides. I want to raise a decision that belongs to the wider community rather than to a code review.

Current state

Django rewrites the text Sphinx generates for version annotations making versionadded and versionchanged go through a custom directive and a custom HTML writer override, so they render as “New in Django 6.1” and “Changed in Django 6.1”. deprecated was never covered by that code and goes through Sphinx untouched, so it renders as “Deprecated since version 6.1”.

That inconsistency (“Django” vs “version”) is live today. The same page can show “Deprecated since version 6.1” and “Changed in Django 6.1” in adjacent boxes:

Furthermore:

  • The “Django” wording lives in an HTML writer override, so the other builders (PDF, etc) never get it.
  • Our own contributor docs have already drifted: docs/intro/whatsnext.txt tells readers we use “New in Django Development version” for unreleased versions and “New in version X.Y” for released ones, but released versions actually render “New in Django X.Y”.
  • docs/internals/contributing/writing-documentation.txt documents the versionadded and versionchanged wording and says nothing about deprecated.
  • versionremoved, added in Sphinx 7.3, has no Django wording at all.
  • Sphinx 9.0 added hyphenated aliases (version-added, version-changed, etc.). Our custom handling does not cover them, and nothing stops a contributor from using them.
  • The development version substitution renders with a stray capital: “New in Django Development version”.
  • The custom code emits <span class="title"> where Sphinx emits <span class="versionmodified">, so the two shapes have to be styled separately on djangoproject.com and neither works cleanly with third-party themes.

Proposal

Remove the customizations and use Sphinx’s wording: “Added in version 6.1”, “Changed in version 6.1”, “Deprecated since version 6.1”. Benefits:

  • Consistency: all directives render the same way, in every output format (html, pdf, epub, etc), immediately. No more “Django” in one box and “version” in the next.
  • Less maintenance: the custom directive, the writer override, and a few more supporting bits all go away.
  • Free wins: new changeset types and new directive aliases work the moment we upgrade Sphinx, instead of silently falling through our custom handling.
  • Localization: Sphinx ships translations for these strings. Our custom strings are in no catalog, so translated docs show them in English today. See for example current docs for fr:
  • Theme portability: standard markup is a precondition for replacing our unmaintained djangodocs theme, which is ticket #37138.
  • Familiarity: it matches what readers see in Python’s own documentation and in every other Sphinx-based project.

Two downsides (though none of these seem worth the ongoing cost to me):

  • The wording changes throughout the documentation and it will be visible across versions (before 6.2 vs after).
  • The development docs would say “Changed in version 6.2” before 6.2 (officially) exists, instead of “Changed in Django development version”. CPython’s dev docs do exactly this, and naming the release is arguably more useful than not naming it, but it is a change.

Thoughts welcome, particularly from anyone who feels strongly about the “Django N.M” phrasing. Thanks to Mike for the analysis in #37212 and for raising the question in the first place.

9 Likes

This sounds very reasonable, as described. I’m always inclined to find out why things are as they are before changing anything.

The extensions here have been around for a long time, so I’d probably ask @jacobian and @timgraham if they’re able to provide the historical context?

2 Likes

I think it should be fine.

As for the original “why,” there’s a note in the commit that added original versionadded/changed annotations: “Turn the “new in version” stuff (versionadded/versionchanged) into a better callout – the Sphinx default is just a little span, which is a bit less obvious that I’d like.”

4 Likes

Thanks @nessita for raising the discussion, and to everyone who weighed in (currently at 9 :heart: + :+1: with no apparent downvotes).

I’ve updated PR #21613 to remove the custom directive overrides.

That’s helpful. It was true when the comment was written, but hasn’t been accurate for many years. It looks like Sphinx came to the same realization not long after and replaced docutils’ changeset directives with their own—including better and more-stylable html output.

(Some of the other code that PR removes from the djangodocs extension is similar workarounds for older Sphinx shortcomings that newer Sphinx versions have addressed.)

2 Likes