Building and checking the documentation

Building the documentation requires Python 3.11+ (required by sphinx-design 0.7). The library itself supports Python 3.10+. From the repository root, run:

uv sync --locked --group docs
uv run --no-sync python -m sphinx -E -a -n -W --keep-going -b html -D language=ru docs docs/_build/html/ru
uv run --no-sync python -m sphinx -E -a -n -W --keep-going -b html -D language=en docs docs/_build/html/en
uv run --no-sync python -m sphinx -E -a -n -W --keep-going -b doctest -D language=ru docs docs/_build/doctest/ru
uv run --no-sync python -m sphinx -E -a -n -W --keep-going -b doctest -D language=en docs docs/_build/doctest/en
uv run --no-sync python -m sphinx -E -a -n -W --keep-going -b gettext docs docs/_build/gettext
uv run --no-sync python docs/check.py

The Russian version is at docs/_build/html/ru/index.html and the English version at docs/_build/html/en/index.html. An HTML build into a ru or en directory automatically creates a shared index.html beside it. Publish the entire docs/_build/html directory: the entry page selects Russian when the primary browser language is ru or ru-*, and English for all other languages or when no preference is available. Direct links to ru/ and en/ are not redirected; the language switcher opens the same page in the other version. Without JavaScript, the entry page provides links to both languages. -E -a forces Sphinx to reread all sources, -n checks API references, and -W treats warnings as errors. --keep-going collects all problems in a single run. Python intersphinx requires access to https://docs.python.org/3/objects.inv; a failed download also fails the strict build.

Doctest executes the examples, checking assertions and exact output, including hex. docs/check.py also checks local HTML files and link anchors, including links between languages, public export targets in each version, translation coverage against fresh gettext catalogs, relative README links, and the README Python example. Comments next to print calls in the README specify the expected output. Local link checks do not access external sites.

Adding examples

Use testcode for ordinary Python code and testoutput for expected output. Multiple blocks on a page can continue the same example; independent scenarios can use separate groups. :hide: hides the expected output without disabling its check. Use assert to check examples that produce no output. Compute hex by running the example, then record the expected value in the documentation.

Construct is only needed for the executable comparison in Why bytespec?. It is included in the docs group and is not a bytespec runtime dependency. Do not replace its example with untested pseudocode.

The configuration uses Sphinx, Furo, autodoc, and an explicit list of public entry points. conf.py adds src to the import path; once dependencies are installed, commands can also run through .venv/bin/python. The version comes from distribution metadata or, without an installation, from pyproject.toml via tomllib (this fallback requires Python 3.11+). The library itself requires Python 3.10+.

Updating the translation

The source .rst files are written in Russian, and library docstrings in English. English page translations are stored in docs/locale/en/LC_MESSAGES/*.po and its api/ subdirectory. Russian translations of API docstrings are in docs/locale/ru/LC_MESSAGES/api/*.po. Sphinx applies translations during the build; docstrings in the installed library always remain in English.

After changing the sources, update the catalogs:

uv run --no-sync python -m sphinx -E -a -n -W --keep-going -b gettext docs docs/_build/gettext
uv run --no-sync sphinx-intl update -p docs/_build/gettext -d docs/locale -l en -l ru

Translate new msgstr entries and review entries marked fuzzy; remove that flag after reviewing them. Do not change msgid, API names, link targets, or wire values. When translating code, keep it consistent with testoutput: hidden expected output is shared by both languages. Then repeat both HTML and doctest builds and run docs/check.py. Sphinx compiles .po files to .mo automatically; generated .mo files and _build are not kept in the repository. sphinx-intl is only needed to maintain translations and is included in the docs group.

UI patterns in RST

Use a tab-set with Python, Encoded bytes, and Breakdown tabs only where comparing code with its result helps. testcode and testoutput inside tabs still run in doctest, even when a tab is hidden. Give independent examples matching group names for their code and expected output.

For byte breakdowns, use container:: wire-bytes with short dropdown blocks inside. Put the number, field name, and hex in the title, and the explanation in the expandable body. Use the same pattern with container:: code-notes for code annotations; numbers stay outside copyable Python code. The header diagram uses a grid with the wire-layout class. Shared styles live in _static/interactive.css; no raw HTML is needed.

A reusable block:

.. container:: wire-bytes

   .. dropdown:: ① value · ``00 00 00 2a``

      UInt32: 42, four bytes.

Write UI text in RST so that gettext can extract it. After editing examples, check both languages, narrow screens, keyboard navigation, copying, printing, and reading without JavaScript. Tabs and dropdowns use HTML/CSS; no custom JavaScript is required.