https://github.com/python/cpython/commit/a57d16507cccb69d3d76ae05b52f01627d0bc479
commit: a57d16507cccb69d3d76ae05b52f01627d0bc479
branch: main
author: Stan Ulbrych <[email protected]>
committer: StanFromIreland <[email protected]>
date: 2026-09-27T11:36:41+01:00
summary:

gh-156360: Improve `turtle` translation support (#156422)

Co-authored-by: Maciej Olko <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-08-26-15-28-59.gh-issue-156360.ctZMHf.rst
M Doc/library/turtle.rst
M Doc/whatsnew/3.16.rst
M Lib/test/test_turtle.py
M Lib/turtle.py

diff --git a/Doc/library/turtle.rst b/Doc/library/turtle.rst
index 8affcc9ef79defd..cf4ce99e482f216 100644
--- a/Doc/library/turtle.rst
+++ b/Doc/library/turtle.rst
@@ -2689,12 +2689,51 @@ These modified docstrings are created automatically 
together with the function
 definitions that are derived from the methods at import time.
 
 
+.. _turtle-docstring-translation:
+
 Translation of docstrings into different languages
 --------------------------------------------------
 
-There is a utility to create a dictionary the keys of which are the method 
names
-and the values of which are the docstrings of the public methods of the classes
-Screen and Turtle.
+The docstrings of the public methods of the Screen and Turtle classes, and of
+the corresponding functions, can be replaced with translations, so that
+:func:`help` and IDE tooltips are shown in another language. However, only the 
help
+text is translated, the names of the functions and methods stay the same.
+
+Translations are distributed on PyPI in the :pypi:`turtle-translations`
+package. To use them, install the package with :program:`pip` and select the
+language with the :envvar:`PYTHON_TURTLE_LANG` environment variable. For
+example, to show the help text in Spanish:
+
+.. code-block:: console
+
+   $ python -m pip install turtle-translations
+   $ PYTHON_TURTLE_LANG=es python
+   >>> import turtle
+   >>> help(turtle.forward)
+
+The language can also be set permanently with the *language* entry of the
+:file:`turtle.cfg` file (see :ref:`turtle-configuration`). If no translation
+is found for the selected language, the English docstrings are kept.
+
+To add a new language or improve an existing translation, see the
+contribution instructions in the :pypi:`turtle-translations` project.
+
+A translation is a docstring dictionary. It is a top-level module named
+:samp:`turtle_docstringdict_{language}.py` on :data:`sys.path` defining a
+dictionary named ``docsdict``, the keys of which are method names such as
+``Turtle.forward`` and the values of which are the translated docstrings. It is
+read in at import time. Entries naming a method which does not exist in the
+running version are ignored.
+
+.. versionchanged:: 3.16
+   Entries naming an unknown method are ignored instead of reported.
+
+.. envvar:: PYTHON_TURTLE_LANG
+
+   The name of the language to read the translation for. It takes precedence
+   over the *language* entry of the :file:`turtle.cfg` file.
+
+   .. versionadded:: 3.16
 
 .. function:: write_docstringdict(filename="turtle_docstringdict")
 
@@ -2706,17 +2745,8 @@ Screen and Turtle.
    Python script :file:`{filename}.py`.  It is intended to serve as a template
    for translation of the docstrings into different languages.
 
-If you (or your students) want to use :mod:`!turtle` with online help in your
-native language, you have to translate the docstrings and save the resulting
-file as e.g. :file:`turtle_docstringdict_german.py`.
-
-If you have an appropriate entry in your :file:`turtle.cfg` file this 
dictionary
-will be read in at import time and will replace the original English 
docstrings.
-
-At the time of this writing there are docstring dictionaries in German and in
-Italian.  (Requests please to [email protected].)
-
 
+.. _turtle-configuration:
 
 How to configure Screen and Turtles
 -----------------------------------
@@ -2767,9 +2797,9 @@ Short explanation of selected entries:
   the cfg file).
 - If you want to reflect the turtle its state, you have to use ``resizemode =
   auto``.
-- If you set e.g. ``language = italian`` the docstringdict
-  :file:`turtle_docstringdict_italian.py` will be loaded at import time (if
-  present on the import path, e.g. in the same directory as :mod:`!turtle`).
+- The *language* entry selects the language of the docstrings, unless the
+  :envvar:`PYTHON_TURTLE_LANG` environment variable is set. See
+  :ref:`turtle-docstring-translation` for more information.
 - The entries *exampleturtle* and *examplescreen* define the names of these
   objects as they occur in the docstrings.  The transformation of
   method-docstrings to function-docstrings will delete these names from the
diff --git a/Doc/whatsnew/3.16.rst b/Doc/whatsnew/3.16.rst
index 7a1f9410c87fc7d..c61190822234ead 100644
--- a/Doc/whatsnew/3.16.rst
+++ b/Doc/whatsnew/3.16.rst
@@ -712,6 +712,16 @@ tkinter
   with no unit suffix to :class:`int` or :class:`float`.
   (Contributed by Serhiy Storchaka in :gh:`153513`.)
 
+
+turtle
+------
+
+* Translations of the :mod:`turtle` docstrings are now distributed on PyPI
+  in the :pypi:`turtle-translations` package. Additionally, added the
+  :envvar:`PYTHON_TURTLE_LANG` environment variable to select the language.
+  (Contributed by Stan Ulbrych in :gh:`156360`.)
+
+
 unicodedata
 -----------
 
diff --git a/Lib/test/test_turtle.py b/Lib/test/test_turtle.py
index c49ce9cdb6f6d95..7e24f1d526a1bcb 100644
--- a/Lib/test/test_turtle.py
+++ b/Lib/test/test_turtle.py
@@ -7,6 +7,7 @@
 from test import support
 from test.support import import_helper
 from test.support import os_helper
+from test.support.script_helper import assert_python_ok
 
 
 turtle = import_helper.import_module('turtle')
@@ -713,5 +714,33 @@ def test_all_signatures(self):
                 self.assertEqual(str(sig), known_signatures[name])
 
 
+class TurtleDocstringTranslationTest(unittest.TestCase):
+
+    def _make_translation(self, dirname, filename, docstring):
+        with open(os.path.join(dirname, filename), 'w') as f:
+            f.write('docsdict = {"Turtle.forward": %r}\n' % docstring)
+
+    def _get_forward_docstring(self, dirname, lang):
+        rc, out, err = assert_python_ok(
+            '-c', 'import turtle; print(turtle.forward.__doc__)',
+            PYTHONPATH=dirname, PYTHON_TURTLE_LANG=lang)
+        return out.decode()
+
+    def test_translation(self):
+        with os_helper.temp_dir() as dirname:
+            self._make_translation(dirname, 'turtle_docstringdict_ga.py',
+                                  'chun tosaigh')
+
+            out = self._get_forward_docstring(dirname, 'ga')
+            self.assertIn('chun tosaigh', out)
+
+    def test_unknown_language(self):
+        with os_helper.temp_dir() as dirname:
+            out = self._get_forward_docstring(dirname, 'ga')
+
+            self.assertIn('Cannot find docsdict for ga', out)
+            self.assertIn('Move the turtle forward', out)
+
+
 if __name__ == '__main__':
     unittest.main()
diff --git a/Lib/turtle.py b/Lib/turtle.py
index b49df26bd07bc5a..13cd2d8b7e73cb3 100644
--- a/Lib/turtle.py
+++ b/Lib/turtle.py
@@ -105,6 +105,7 @@
 import inspect
 import sys
 
+from os import environ
 from os.path import isfile, split, join
 from pathlib import Path
 from contextlib import contextmanager
@@ -4017,18 +4018,24 @@ def read_docstrings(lang):
     Transfer docstrings, translated to lang, from a dictionary-file
     to the methods of classes Screen and Turtle and - in revised form -
     to the corresponding functions.
+
+    Entries naming a method which does not exist in this version are
+    ignored.
     """
-    modname = "turtle_docstringdict_%(language)s" % {'language':lang.lower()}
-    module = __import__(modname)
+    module = __import__(f"turtle_docstringdict_{lang.lower()}")
     docsdict = module.docsdict
     for key in docsdict:
         try:
 #            eval(key).im_func.__doc__ = docsdict[key]
             eval(key).__doc__ = docsdict[key]
+        except AttributeError:
+            pass
         except Exception:
             print("Bad docstring-entry: %s" % key)
 
 _LANGUAGE = _CFG["language"]
+if not sys.flags.ignore_environment:
+    _LANGUAGE = environ.get("PYTHON_TURTLE_LANG") or _LANGUAGE
 
 try:
     if _LANGUAGE != "english":
diff --git 
a/Misc/NEWS.d/next/Library/2026-08-26-15-28-59.gh-issue-156360.ctZMHf.rst 
b/Misc/NEWS.d/next/Library/2026-08-26-15-28-59.gh-issue-156360.ctZMHf.rst
new file mode 100644
index 000000000000000..d0d9f5570cbd5c2
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-08-26-15-28-59.gh-issue-156360.ctZMHf.rst
@@ -0,0 +1,3 @@
+Add the :envvar:`PYTHON_TURTLE_LANG` environment variable to select the
+language of :mod:`turtle` docstrings. Docstring dictionary entries naming a
+method which does not exist in the running version are no longer reported.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to