Skip to content

Commit 906cf7c

Browse files
Improve turtle translation support
1 parent f54fd2a commit 906cf7c

4 files changed

Lines changed: 107 additions & 20 deletions

File tree

Doc/library/turtle.rst

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2675,12 +2675,47 @@ These modified docstrings are created automatically together with the function
26752675
definitions that are derived from the methods at import time.
26762676

26772677

2678+
.. _turtle-docstring-translation:
2679+
26782680
Translation of docstrings into different languages
26792681
--------------------------------------------------
26802682

2681-
There is a utility to create a dictionary the keys of which are the method names
2682-
and the values of which are the docstrings of the public methods of the classes
2683-
Screen and Turtle.
2683+
The docstrings of the public methods of the Screen and Turtle classes, and of
2684+
the functions derived from them, can be replaced by translations, so that
2685+
:func:`help` and IDE tooltips are shown in another language.
2686+
2687+
The translations are not part of Python. They are distributed on PyPI in the
2688+
:pypi:`turtle-translations` package, which holds the docstring dictionaries of
2689+
all available languages. To use it, you must first install it with :program:`pip`::
2690+
2691+
python -m pip install turtle-translations
2692+
2693+
The language is taken from the :envvar:`PYTHON_TURTLE_LANG` environment
2694+
variable, or, if that is unset, from the ``language`` entry of the
2695+
:file:`turtle.cfg` file. If no docstring dictionary is found for it, the
2696+
English docstrings are kept.
2697+
2698+
.. envvar:: PYTHON_TURTLE_LANG
2699+
2700+
The name of the language to read the docstring dictionary for.
2701+
2702+
.. versionadded:: 3.16
2703+
2704+
A docstring dictionary is a module defining a dictionary named ``docsdict``,
2705+
the keys of which are method names such as ``Turtle.forward`` and the values of
2706+
which are the translated docstrings. It is looked up on :data:`sys.path`, first
2707+
as the submodule of that name of a package named :mod:`!turtle_translations`,
2708+
then as a top-level module named :samp:`turtle_docstringdict_{language}.py`,
2709+
and is read in at import time. Entries naming a method which does not exist in
2710+
the running version are ignored.
2711+
2712+
.. versionchanged:: 3.16
2713+
The docstring dictionary may also be provided as a submodule of a
2714+
:mod:`!turtle_translations` package, and entries naming an unknown method
2715+
are ignored instead of reported.
2716+
2717+
To translate the docstrings into a language which is not available yet, write
2718+
out a template with :func:`write_docstringdict` and translate its values.
26842719

26852720
.. function:: write_docstringdict(filename="turtle_docstringdict")
26862721

@@ -2692,17 +2727,6 @@ Screen and Turtle.
26922727
Python script :file:`{filename}.py`. It is intended to serve as a template
26932728
for translation of the docstrings into different languages.
26942729

2695-
If you (or your students) want to use :mod:`!turtle` with online help in your
2696-
native language, you have to translate the docstrings and save the resulting
2697-
file as e.g. :file:`turtle_docstringdict_german.py`.
2698-
2699-
If you have an appropriate entry in your :file:`turtle.cfg` file this dictionary
2700-
will be read in at import time and will replace the original English docstrings.
2701-
2702-
At the time of this writing there are docstring dictionaries in German and in
2703-
Italian. (Requests please to glingl@aon.at.)
2704-
2705-
27062730

27072731
How to configure Screen and Turtles
27082732
-----------------------------------
@@ -2753,9 +2777,9 @@ Short explanation of selected entries:
27532777
the cfg file).
27542778
- If you want to reflect the turtle its state, you have to use ``resizemode =
27552779
auto``.
2756-
- If you set e.g. ``language = italian`` the docstringdict
2757-
:file:`turtle_docstringdict_italian.py` will be loaded at import time (if
2758-
present on the import path, e.g. in the same directory as :mod:`!turtle`).
2780+
- The *language* entry selects the language of the docstrings, unless the
2781+
:envvar:`PYTHON_TURTLE_LANG` environment variable is set. See
2782+
:ref:`turtle-docstring-translation` for more information.
27592783
- The entries *exampleturtle* and *examplescreen* define the names of these
27602784
objects as they occur in the docstrings. The transformation of
27612785
method-docstrings to function-docstrings will delete these names from the

Lib/test/test_turtle.py

Lines changed: 44 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,48 @@ 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 _make_package(self, dirname):
724+
pkgdir = os.path.join(dirname, 'turtle_translations')
725+
os.mkdir(pkgdir)
726+
with open(os.path.join(pkgdir, '__init__.py'), 'w'):
727+
pass
728+
return pkgdir
729+
730+
def _get_forward_docstring(self, dirname, lang):
731+
rc, out, err = assert_python_ok(
732+
'-c', 'import turtle; print(turtle.forward.__doc__)',
733+
PYTHONPATH=dirname, PYTHON_TURTLE_LANG=lang)
734+
return out.decode()
735+
736+
def test_translation_from_package(self):
737+
with os_helper.temp_dir() as dirname:
738+
pkgdir = self._make_package(dirname)
739+
self._make_translation(pkgdir, 'ga.py', 'chun tosaigh')
740+
741+
out = self._get_forward_docstring(dirname, 'ga')
742+
self.assertIn('chun tosaigh', out)
743+
744+
def test_translation_from_top_level_dict(self):
745+
with os_helper.temp_dir() as dirname:
746+
self._make_translation(dirname, 'turtle_docstringdict_ga.py',
747+
'chun tosaigh')
748+
749+
out = self._get_forward_docstring(dirname, 'ga')
750+
self.assertIn('chun tosaigh', out)
751+
752+
def test_unknown_language(self):
753+
with os_helper.temp_dir() as dirname:
754+
out = self._get_forward_docstring(dirname, 'ga')
755+
756+
self.assertIn('Cannot find docsdict for ga', out)
757+
self.assertIn('Move the turtle forward', out)
758+
759+
716760
if __name__ == '__main__':
717761
unittest.main()

Lib/turtle.py

Lines changed: 17 additions & 3 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,31 @@ 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+
The dictionary is looked up as the submodule lang of the package
4023+
turtle_translations, then as the top-level module
4024+
turtle_docstringdict_lang.
4025+
4026+
Entries naming a method which does not exist in this version are
4027+
ignored.
40204028
"""
4021-
modname = "turtle_docstringdict_%(language)s" % {'language':lang.lower()}
4022-
module = __import__(modname)
4029+
import importlib
4030+
lang = lang.lower()
4031+
try:
4032+
module = importlib.import_module("turtle_translations.%s" % lang)
4033+
except ModuleNotFoundError:
4034+
module = importlib.import_module("turtle_docstringdict_%s" % lang)
40234035
docsdict = module.docsdict
40244036
for key in docsdict:
40254037
try:
40264038
# eval(key).im_func.__doc__ = docsdict[key]
40274039
eval(key).__doc__ = docsdict[key]
4040+
except AttributeError:
4041+
pass
40284042
except Exception:
40294043
print("Bad docstring-entry: %s" % key)
40304044

4031-
_LANGUAGE = _CFG["language"]
4045+
_LANGUAGE = environ.get("PYTHON_TURTLE_LANG") or _CFG["language"]
40324046

40334047
try:
40344048
if _LANGUAGE != "english":
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Add the :envvar:`PYTHON_TURTLE_LANG` environment variable to select the
2+
language of :mod:`turtle` docstrings, and allow the docstring dictionary to
3+
be provided as a submodule of the :pypi:`turtle-translations` package.
4+
Entries naming a method which does not exist in the running version are now
5+
ignored.

0 commit comments

Comments
 (0)