#14261·pip

Gettext internationalization broken for requirements-file options list

Author: hwhsu1231Created Aug 18, 2026Updated Sep 24, 2026
Labelstype: bugS: needs triage

Description

This issue was found when I was incubating the pip-docs-l10n project.

I found that building the documentation with the gettext builder produces malformed entries for the pip-requirements-file-options-ref-list directive in docs/html/reference/requirements-file-format.md:

  1. A single merged msgid that concatenates every supported option label.
  2. Individual entries whose source location is broken (#: ../../\n:1) and whose msgid still contains raw RST :ref: markup.

Additionally, after translating the extracted entries to .po and building the translated documentation, the rendered page shows :ref: as literal text and the cross-reference links are dropped.

The directive is implemented in docs/pip_sphinxext.py (PipReqFileOptionsReference):

https://github.com/pypa/pip/blob/0ed2d3e775db5c1af01311fbb6c2c6b55b0c4d70/docs/pip_sphinxext.py#L215-L244

Expected behavior

  • Each supported option is extracted as its own well-formed .pot entry with a valid #: <file>:<line> location.
  • The generated entry's msgid should use MyST syntax ({ref}`-i, --index-url <install_--index-url>`) rather than reST syntax (:ref:`-i, --index-url <install_--index-url>`).
  • Translated builds display the translated option labels while preserving the cross-reference links.

pip version

0ed2d3e775db5c1af01311fbb6c2c6b55b0c4d70

Python version

3.14

OS

Linux

How to Reproduce

bash
BRANCH=main
COMMIT=0ed2d3e775db5c1af01311fbb6c2c6b55b0c4d70

# Clone the repository
git clone --branch=$BRANCH https://github.com/pypa/pip.git
cd pip
git checkout $COMMIT

# Prepare the environment and requirements
conda create --prefix ./.venv --yes
conda activate ./.venv
conda install python=3.14 pip=26 -c conda-forge -c nodefaults --yes
export PYTHONNOUSERSITE=1 LANGUAGE=en_US LANG=en_US.UTF-8
python -m pip install . --group docs
python -m pip install sphinx-intl polib

pushd docs/html

# Build .pot files with gettext builder
sphinx-build -b gettext -Dgettext_compact=0 . ../build/pot

# Print the 'reference/requirements-file-format.pot' file (Output 1)
cat ../build/pot/reference/requirements-file-format.pot

# Update .pot files to .po files with sphinx-intl
sphinx-intl update -l zh_TW -p ../build/pot

# Translate the entry
python - << 'PY'
import polib
po_path = "locales/zh_TW/LC_MESSAGES/reference/requirements-file-format.po"
msgid = ":ref:`-i, --index-url<install_--index-url>`"
msgstr = ":ref:`測試翻譯: -i, --index-url<install_--index-url>`"
po = polib.pofile(po_path)
entry = po.find(msgid)
assert entry is not None, f"entry not found: {msgid}"
entry.msgstr = msgstr
po.save(po_path)
PY

# Build the translated documentation
sphinx-build -b html -Dlanguage=zh_TW -Dgettext_compact=0 . ../build/html/zh_TW

popd

# Preview the translated documentation (Output 2)
firefox docs/build/html/zh_TW/reference/requirements-file-format.html

Output

When printing the generated reference/requirements-file-format.pot file, we will see the following content:

Click to expand the specific content
pot
#: ../../html/reference/requirements-file-format.md:10
msgid "-i, --index-url  --extra-index-url  --no-index  -c, --constraint  -r, --requirement  -e, --editable  -f, --find-links  --no-binary  --only-binary  --prefer-binary  --require-hashes  --pre  --all-releases  --only-final  --trusted-host  --use-feature"
msgstr ""

#: ../../html/
:1
msgid ":ref:`-i, --index-url<install_--index-url>`"
msgstr ""

#: ../../html/
:1
msgid ":ref:`--extra-index-url<install_--extra-index-url>`"
msgstr ""

#: ../../html/
:1
msgid ":ref:`--no-index<install_--no-index>`"
msgstr ""

#: ../../html/
:1
msgid ":ref:`-c, --constraint<install_--constraint>`"
msgstr ""

#: ../../html/
:1
msgid ":ref:`-r, --requirement<install_--requirement>`"
msgstr ""

#: ../../html/
:1
msgid ":ref:`-e, --editable<install_--editable>`"
msgstr ""

#: ../../html/
:1
msgid ":ref:`-f, --find-links<install_--find-links>`"
msgstr ""

#: ../../html/
:1
msgid ":ref:`--no-binary<install_--no-binary>`"
msgstr ""

#: ../../html/
:1
msgid ":ref:`--only-binary<install_--only-binary>`"
msgstr ""

#: ../../html/
:1
msgid ":ref:`--prefer-binary<install_--prefer-binary>`"
msgstr ""

#: ../../html/
:1
msgid ":ref:`--require-hashes<install_--require-hashes>`"
msgstr ""

#: ../../html/
:1
msgid ":ref:`--pre<install_--pre>`"
msgstr ""

#: ../../html/
:1
msgid ":ref:`--all-releases<install_--all-releases>`"
msgstr ""

#: ../../html/
:1
msgid ":ref:`--only-final<install_--only-final>`"
msgstr ""

#: ../../html/
:1
msgid ":ref:`--trusted-host<--trusted-host>`"
msgstr ""

#: ../../html/
:1
msgid ":ref:`--use-feature<--use-feature>`"
msgstr ""

When previewing the reference/requirements-file-format.html file in the web browser, we will see the following content:

Image

Code of Conduct