Building and checking the documentation

Run these commands from the checkout root:

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.