Skip to content

Commit a57d165

Browse files
gh-156360: Improve turtle translation support (#156422)
Co-authored-by: Maciej Olko <maciej.olko@affirm.com>
1 parent 7731da1 commit a57d165

5 files changed

Lines changed: 97 additions & 18 deletions

File tree

‎Doc/library/turtle.rst‎

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2689,12 +2689,51 @@ These modified docstrings are created automatically together with the function
26892689
definitions that are derived from the methods at import time.
26902690

26912691

2692+
.. _turtle-docstring-translation:
2693+
26922694
Translation of docstrings into different languages
26932695
--------------------------------------------------
26942696

2695-
There is a utility to create a dictionary the keys of which are the method names
2696-
and the values of which are the docstrings of the public methods of the classes
2697-
Screen and Turtle.
2697+
The docstrings of the public methods of the Screen and Turtle classes, and of
2698+
the corresponding functions, can be replaced with translations, so that
2699+
:func:`help` and IDE tooltips are shown in another language. However, only the help
2700+
text is translated, the names of the functions and methods stay the same.
2701+
2702+
Translations are distributed on PyPI in the :pypi:`turtle-translations`
2703+
package. To use them, install the package with :program:`pip` and select the
2704+
language with the :envvar:`PYTHON_TURTLE_LANG` environment variable. For
2705+
example, to show the help text in Spanish:
2706+
2707+
.. code-block:: console
2708+
2709+
$ python -m pip install turtle-translations
2710+
$ PYTHON_TURTLE_LANG=es python
2711+
>>> import turtle
2712+
>>> help(turtle.forward)
2713+
2714+
The language can also be set permanently with the *language* entry of the
2715+
:file:`turtle.cfg` file (see :ref:`turtle-configuration`). If no translation
2716+
is found for the selected language, the English docstrings are kept.
2717+
2718+
To add a new language or improve an existing translation, see the
2719+
contribution instructions in the :pypi:`turtle-translations` project.
2720+
2721+
A translation is a docstring dictionary. It is a top-level module named
2722+
:samp:`turtle_docstringdict_{language}.py` on :data:`sys.path` defining a
2723+
dictionary named ``docsdict``, the keys of which are method names such as
2724+
``Turtle.forward`` and the values of which are the translated docstrings. It is
2725+
read in at import time. Entries naming a method which does not exist in the
2726+
running version are ignored.
2727+
2728+
.. versionchanged:: 3.16
2729+
Entries naming an unknown method are ignored instead of reported.
2730+
2731+
.. envvar:: PYTHON_TURTLE_LANG
2732+
2733+
The name of the language to read the translation for. It takes precedence
2734+
over the *language* entry of the :file:`turtle.cfg` file.
2735+
2736+
.. versionadded:: 3.16
26982737

26992738
.. function:: write_docstringdict(filename="turtle_docstringdict")
27002739

@@ -2706,17 +2745,8 @@ Screen and Turtle.
27062745
Python script :file:`{filename}.py`. It is intended to serve as a template
27072746
for translation of the docstrings into different languages.
27082747

2709-
If you (or your students) want to use :mod:`!turtle` with online help in your
2710-
native language, you have to translate the docstrings and save the resulting
2711-
file as e.g. :file:`turtle_docstringdict_german.py`.
2712-
2713-
If you have an appropriate entry in your :file:`turtle.cfg` file this dictionary
2714-
will be read in at import time and will replace the original English docstrings.
2715-
2716-
At the time of this writing there are docstring dictionaries in German and in
2717-
Italian. (Requests please to glingl@aon.at.)
2718-
27192748

2749+
.. _turtle-configuration:
27202750

27212751
How to configure Screen and Turtles
27222752
-----------------------------------
@@ -2767,9 +2797,9 @@ Short explanation of selected entries:
27672797
the cfg file).
27682798
- If you want to reflect the turtle its state, you have to use ``resizemode =
27692799
auto``.
2770-
- If you set e.g. ``language = italian`` the docstringdict
2771-
:file:`turtle_docstringdict_italian.py` will be loaded at import time (if
2772-
present on the import path, e.g. in the same directory as :mod:`!turtle`).
2800+
- The *language* entry selects the language of the docstrings, unless the
2801+
:envvar:`PYTHON_TURTLE_LANG` environment variable is set. See
2802+
:ref:`turtle-docstring-translation` for more information.
27732803
- The entries *exampleturtle* and *examplescreen* define the names of these
27742804
objects as they occur in the docstrings. The transformation of
27752805
method-docstrings to function-docstrings will delete these names from the

‎Doc/whatsnew/3.16.rst‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,16 @@ tkinter
712712
with no unit suffix to :class:`int` or :class:`float`.
713713
(Contributed by Serhiy Storchaka in :gh:`153513`.)
714714

715+
716+
turtle
717+
------
718+
719+
* Translations of the :mod:`turtle` docstrings are now distributed on PyPI
720+
in the :pypi:`turtle-translations` package. Additionally, added the
721+
:envvar:`PYTHON_TURTLE_LANG` environment variable to select the language.
722+
(Contributed by Stan Ulbrych in :gh:`156360`.)
723+
724+
715725
unicodedata
716726
-----------
717727

‎Lib/test/test_turtle.py‎

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from test import support
88
from test.support import import_helper
99
from test.support import os_helper
10+
from test.support.script_helper import assert_python_ok
1011

1112

1213
turtle = import_helper.import_module('turtle')
@@ -713,5 +714,33 @@ def test_all_signatures(self):
713714
self.assertEqual(str(sig), known_signatures[name])
714715

715716

717+
class TurtleDocstringTranslationTest(unittest.TestCase):
718+
719+
def _make_translation(self, dirname, filename, docstring):
720+
with open(os.path.join(dirname, filename), 'w') as f:
721+
f.write('docsdict = {"Turtle.forward": %r}\n' % docstring)
722+
723+
def _get_forward_docstring(self, dirname, lang):
724+
rc, out, err = assert_python_ok(
725+
'-c', 'import turtle; print(turtle.forward.__doc__)',
726+
PYTHONPATH=dirname, PYTHON_TURTLE_LANG=lang)
727+
return out.decode()
728+
729+
def test_translation(self):
730+
with os_helper.temp_dir() as dirname:
731+
self._make_translation(dirname, 'turtle_docstringdict_ga.py',
732+
'chun tosaigh')
733+
734+
out = self._get_forward_docstring(dirname, 'ga')
735+
self.assertIn('chun tosaigh', out)
736+
737+
def test_unknown_language(self):
738+
with os_helper.temp_dir() as dirname:
739+
out = self._get_forward_docstring(dirname, 'ga')
740+
741+
self.assertIn('Cannot find docsdict for ga', out)
742+
self.assertIn('Move the turtle forward', out)
743+
744+
716745
if __name__ == '__main__':
717746
unittest.main()

‎Lib/turtle.py‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
import inspect
106106
import sys
107107

108+
from os import environ
108109
from os.path import isfile, split, join
109110
from pathlib import Path
110111
from contextlib import contextmanager
@@ -4017,18 +4018,24 @@ def read_docstrings(lang):
40174018
Transfer docstrings, translated to lang, from a dictionary-file
40184019
to the methods of classes Screen and Turtle and - in revised form -
40194020
to the corresponding functions.
4021+
4022+
Entries naming a method which does not exist in this version are
4023+
ignored.
40204024
"""
4021-
modname = "turtle_docstringdict_%(language)s" % {'language':lang.lower()}
4022-
module = __import__(modname)
4025+
module = __import__(f"turtle_docstringdict_{lang.lower()}")
40234026
docsdict = module.docsdict
40244027
for key in docsdict:
40254028
try:
40264029
# eval(key).im_func.__doc__ = docsdict[key]
40274030
eval(key).__doc__ = docsdict[key]
4031+
except AttributeError:
4032+
pass
40284033
except Exception:
40294034
print("Bad docstring-entry: %s" % key)
40304035

40314036
_LANGUAGE = _CFG["language"]
4037+
if not sys.flags.ignore_environment:
4038+
_LANGUAGE = environ.get("PYTHON_TURTLE_LANG") or _LANGUAGE
40324039

40334040
try:
40344041
if _LANGUAGE != "english":
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Add the :envvar:`PYTHON_TURTLE_LANG` environment variable to select the
2+
language of :mod:`turtle` docstrings. Docstring dictionary entries naming a
3+
method which does not exist in the running version are no longer reported.

0 commit comments

Comments
 (0)