Skip to content

Commit 9638aea

Browse files
authored
Merge pull request python#27 from raulcd/rst2po
Script `rst2po.py` to migrate tutorial.python.org.ar to this new version
2 parents 912fe24 + 322f1a7 commit 9638aea

15 files changed

+2415
-714
lines changed

.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@
33
url = https://github.com/python/cpython.git
44
branch = 3.7
55
shallow = true
6+
[submodule "tutorialpyar"]
7+
path = .migration/tutorialpyar
8+
url = https://github.com/pyar/tutorial.git

.migration/rst2po.py

+134
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# rst2po.py
2+
# Script to migrate the Python official tutorial that we have already translated in PyAr
3+
# (https://github.com/PyAr/tutorial) from reStructuredText to the new official translation format (.po)
4+
#
5+
# It parses the .rst and compare sentence/paragraph by sentence/paragraph and if the match is exact,
6+
# and there is no translation for that sentence/paragraph it updates the .po file with the translated text
7+
# from the .rst file.
8+
9+
import re
10+
import glob
11+
import os
12+
import polib # fades
13+
14+
15+
PO_DIR = os.path.abspath(
16+
os.path.join(
17+
os.path.dirname(__file__),
18+
'..',
19+
))
20+
21+
RST_TRADUCIDOS_DIR = os.path.abspath(
22+
os.path.join(
23+
os.path.dirname(__file__),
24+
'tutorialpyar',
25+
'traducidos',
26+
))
27+
28+
RST_ORIGINAL_DIR = os.path.abspath(
29+
os.path.join(
30+
os.path.dirname(__file__),
31+
'tutorialpyar',
32+
'original',
33+
))
34+
35+
36+
37+
def get_rst_file(pofilename):
38+
"""Given a .po filename returns the corresponding .rst filename"""
39+
basename = os.path.basename(pofilename)
40+
basename, ext = basename.rsplit('.', 1)
41+
rstfilename = os.path.join(RST_TRADUCIDOS_DIR, f'{basename}.rst')
42+
if os.path.exists(rstfilename):
43+
return rstfilename
44+
45+
46+
def get_rst_original_filename(rstfilename):
47+
rst_original_filename = ''
48+
if rstfilename.endswith('real-index.rst'):
49+
rst_original_filename = 'index.rst'
50+
51+
basename = os.path.basename(rst_original_filename or rstfilename)
52+
rst_original_filename = os.path.join(RST_ORIGINAL_DIR, basename)
53+
if os.path.exists(rst_original_filename):
54+
return rst_original_filename
55+
56+
57+
def create_english_spanish_sentences(rstfilename):
58+
"""Create a tuple of (english, spanish) sentences for rstfilename"""
59+
60+
def get_paragraph(fd):
61+
lines = []
62+
paragraph = []
63+
for line in fd.read().splitlines():
64+
# import pdb; pdb.set_trace()
65+
if any([
66+
line.startswith('.. '),
67+
line.startswith('==='),
68+
line.startswith('---'),
69+
line.startswith('***'),
70+
]):
71+
continue
72+
73+
if line == '' and not paragraph:
74+
continue
75+
76+
if line == '':
77+
lines.append(' '.join(paragraph))
78+
paragraph = []
79+
continue
80+
paragraph.append(line)
81+
82+
return lines
83+
84+
# NOTE: we could use docutils and parse the rst in the correct way, but
85+
# that will probably take more time
86+
with open(get_rst_original_filename(rstfilename)) as fd:
87+
english = get_paragraph(fd)
88+
89+
with open(rstfilename) as fd:
90+
spanish = get_paragraph(fd)
91+
92+
result = list(zip(english, spanish))
93+
return result
94+
95+
96+
def get_rst_translation_text(rstfilename, english_spanish, text):
97+
"""Given an rstfilename an a text returns the corresponding translated text if exists"""
98+
for en, es in english_spanish:
99+
if en.replace("!", "") == text.replace("!", ""):
100+
return es
101+
102+
103+
def update_po_translation(pofilename, english, spanish):
104+
"""Update the pofilename with the translated spanish text"""
105+
pass
106+
107+
108+
for pofilename in glob.glob(PO_DIR + '**/*/*.po'):
109+
translated = False
110+
rstfilename = get_rst_file(pofilename)
111+
if rstfilename is None:
112+
continue
113+
114+
english_spanish = create_english_spanish_sentences(rstfilename)
115+
116+
po = polib.pofile(pofilename)
117+
for entry in po:
118+
english_text = entry.msgid
119+
spanish_text = entry.msgstr
120+
if spanish_text:
121+
# Do not override already translated text
122+
continue
123+
124+
translated_text = get_rst_translation_text(rstfilename, english_spanish, english_text)
125+
if translated_text is None:
126+
continue
127+
128+
translated = True
129+
130+
entry.msgstr = translated_text
131+
# update_po_translation(po, english_text, translated_text)
132+
133+
if translated:
134+
po.save(pofilename)

.migration/tutorialpyar

Submodule tutorialpyar added at 0349d89

tutorial/appendix.po

+91-30
Original file line numberDiff line numberDiff line change
@@ -18,63 +18,90 @@ msgstr ""
1818

1919
#: ../Doc/tutorial/appendix.rst:5
2020
msgid "Appendix"
21-
msgstr ""
21+
msgstr "Apéndice"
2222

2323
#: ../Doc/tutorial/appendix.rst:11
2424
msgid "Interactive Mode"
25-
msgstr ""
25+
msgstr "Modo interactivo"
2626

2727
#: ../Doc/tutorial/appendix.rst:16
2828
msgid "Error Handling"
29-
msgstr ""
29+
msgstr "Manejo de errores"
3030

3131
#: ../Doc/tutorial/appendix.rst:18
3232
msgid ""
3333
"When an error occurs, the interpreter prints an error message and a stack "
3434
"trace. In interactive mode, it then returns to the primary prompt; when "
3535
"input came from a file, it exits with a nonzero exit status after printing "
36-
"the stack trace. (Exceptions handled by an :keyword:`except` clause in a :"
37-
"keyword:`try` statement are not errors in this context.) Some errors are "
38-
"unconditionally fatal and cause an exit with a nonzero exit; this applies to "
39-
"internal inconsistencies and some cases of running out of memory. All error "
40-
"messages are written to the standard error stream; normal output from "
36+
"the stack trace. (Exceptions handled by an :keyword:`except` clause in a "
37+
":keyword:`try` statement are not errors in this context.) Some errors are "
38+
"unconditionally fatal and cause an exit with a nonzero exit; this applies to"
39+
" internal inconsistencies and some cases of running out of memory. All "
40+
"error messages are written to the standard error stream; normal output from "
4141
"executed commands is written to standard output."
4242
msgstr ""
43+
"Cuando ocurre un error, el intérprete imprime un mensaje de error y la traza"
44+
" del error. En el modo interactivo, luego retorna al prompt primario; "
45+
"cuando la entrada viene de un archivo, el programa termina con código de "
46+
"salida distinto a cero luego de imprimir la traza del error. (Las "
47+
"excepciones manejadas por una clausula :keyword:`except` en una sentencia "
48+
":keyword:`try` no son errores en este contexto). Algunos errores son "
49+
"incondicionalmente fatales y causan una terminación con código de salida "
50+
"distinto de cero; esto se debe a inconsistencias internas o a que el "
51+
"intérprete se queda sin memoria. Todos los mensajes de error se escriben en "
52+
"el flujo de errores estándar; las salidas normales de comandos ejecutados se"
53+
" escriben en la salida estándar."
4354

4455
#: ../Doc/tutorial/appendix.rst:28
4556
msgid ""
4657
"Typing the interrupt character (usually :kbd:`Control-C` or :kbd:`Delete`) "
4758
"to the primary or secondary prompt cancels the input and returns to the "
48-
"primary prompt. [#]_ Typing an interrupt while a command is executing raises "
49-
"the :exc:`KeyboardInterrupt` exception, which may be handled by a :keyword:"
50-
"`try` statement."
59+
"primary prompt. [#]_ Typing an interrupt while a command is executing raises"
60+
" the :exc:`KeyboardInterrupt` exception, which may be handled by a "
61+
":keyword:`try` statement."
5162
msgstr ""
63+
"Al ingresar el caracter de interrupción (por lo general :kbd:`Control-C` o "
64+
":kbd:`Supr`) en el prompt primario o secundario, se cancela la entrada y "
65+
"retorna al prompt primario. [#]_ Tipear una interrupción mientras un "
66+
"comando se están ejecutando lanza la excepción :exc:`KeyboardInterrupt`, que"
67+
" puede ser manejada con una sentencia :keyword:`try`."
5268

5369
#: ../Doc/tutorial/appendix.rst:38
5470
msgid "Executable Python Scripts"
55-
msgstr ""
71+
msgstr "Programas ejecutables de Python"
5672

5773
#: ../Doc/tutorial/appendix.rst:40
5874
msgid ""
5975
"On BSD'ish Unix systems, Python scripts can be made directly executable, "
6076
"like shell scripts, by putting the line ::"
6177
msgstr ""
78+
"En los sistemas Unix y tipo BSD, los programas Python pueden convertirse "
79+
"directamente en ejecutables, como programas del intérprete de comandos, "
80+
"poniendo la linea::"
6281

6382
#: ../Doc/tutorial/appendix.rst:45
6483
msgid ""
6584
"(assuming that the interpreter is on the user's :envvar:`PATH`) at the "
6685
"beginning of the script and giving the file an executable mode. The ``#!`` "
67-
"must be the first two characters of the file. On some platforms, this first "
68-
"line must end with a Unix-style line ending (``'\\n'``), not a Windows "
86+
"must be the first two characters of the file. On some platforms, this first"
87+
" line must end with a Unix-style line ending (``'\\n'``), not a Windows "
6988
"(``'\\r\\n'``) line ending. Note that the hash, or pound, character, "
7089
"``'#'``, is used to start a comment in Python."
7190
msgstr ""
91+
"...al principio del script y dándole al archivo permisos de ejecución "
92+
"(asumiendo que el intérprete están en la variable de entorno :envvar:`PATH` "
93+
"del usuario). ``#!`` deben ser los primeros dos caracteres del archivo. En"
94+
" algunas plataformas, la primera línea debe terminar al estilo Unix "
95+
"(``'\\n'``), no como en Windows (``'\\r\\n'``). Notá que el caracter "
96+
"numeral ``'#'`` se usa en Python para comenzar un comentario."
7297

7398
#: ../Doc/tutorial/appendix.rst:52
7499
msgid ""
75-
"The script can be given an executable mode, or permission, using the :"
76-
"program:`chmod` command."
100+
"The script can be given an executable mode, or permission, using the "
101+
":program:`chmod` command."
77102
msgstr ""
103+
"Se le puede dar permisos de ejecución al script usando el comando "
104+
":program:`chmod`::"
78105

79106
#: ../Doc/tutorial/appendix.rst:59
80107
msgid ""
@@ -84,10 +111,15 @@ msgid ""
84111
"extension can also be ``.pyw``, in that case, the console window that "
85112
"normally appears is suppressed."
86113
msgstr ""
114+
"En sistemas Windows, no existe la noción de \"modo ejecutable\". El "
115+
"instalador de Python asocia automáticamente la extensión ``.py`` con "
116+
"``python.exe`` para que al hacerle doble click a un archivo Python se corra "
117+
"el script. La extensión también puede ser ``.pyw``, en este caso se omite "
118+
"la ventana con la consola que normalmente aparece."
87119

88120
#: ../Doc/tutorial/appendix.rst:69
89121
msgid "The Interactive Startup File"
90-
msgstr ""
122+
msgstr "El archivo de inicio interactivo"
91123

92124
#: ../Doc/tutorial/appendix.rst:71
93125
msgid ""
@@ -97,54 +129,83 @@ msgid ""
97129
"the name of a file containing your start-up commands. This is similar to "
98130
"the :file:`.profile` feature of the Unix shells."
99131
msgstr ""
132+
"Cuando usás Python en forma interactiva, suele ser útil que algunos comandos"
133+
" estándar se ejecuten cada vez que el intérprete se inicia. Podés hacer "
134+
"esto configurando la variable de entorno :envvar:`PYTHONSTARTUP` con el "
135+
"nombre de un archivo que contenga tus comandos de inicio. Esto es similar "
136+
"al archivo :file:`.profile` en los intérpretes de comandos de Unix."
100137

101138
#: ../Doc/tutorial/appendix.rst:77
102139
msgid ""
103140
"This file is only read in interactive sessions, not when Python reads "
104141
"commands from a script, and not when :file:`/dev/tty` is given as the "
105142
"explicit source of commands (which otherwise behaves like an interactive "
106143
"session). It is executed in the same namespace where interactive commands "
107-
"are executed, so that objects that it defines or imports can be used without "
108-
"qualification in the interactive session. You can also change the prompts "
144+
"are executed, so that objects that it defines or imports can be used without"
145+
" qualification in the interactive session. You can also change the prompts "
109146
"``sys.ps1`` and ``sys.ps2`` in this file."
110147
msgstr ""
148+
"Este archivo es solo leído en las sesiones interactivas del intérprete, no "
149+
"cuando Python lee comandos de un script ni cuando :file:`/dev/tty` se "
150+
"explicita como una fuente de comandos (que de otro modo se comporta como una"
151+
" sesión interactiva). Se ejecuta en el mismo espacio de nombres en el que "
152+
"los comandos interactivos se ejecutan, entonces los objetos que define o "
153+
"importa pueden ser usados sin cualificaciones en la sesión interactiva. En "
154+
"este archivo también podés cambiar los prompts ``sys.ps1`` y ``sys.ps2``."
111155

112156
#: ../Doc/tutorial/appendix.rst:85
113157
msgid ""
114158
"If you want to read an additional start-up file from the current directory, "
115-
"you can program this in the global start-up file using code like ``if os."
116-
"path.isfile('.pythonrc.py'): exec(open('.pythonrc.py').read())``. If you "
117-
"want to use the startup file in a script, you must do this explicitly in the "
118-
"script::"
159+
"you can program this in the global start-up file using code like ``if "
160+
"os.path.isfile('.pythonrc.py'): exec(open('.pythonrc.py').read())``. If you "
161+
"want to use the startup file in a script, you must do this explicitly in the"
162+
" script::"
119163
msgstr ""
164+
"Si querés leer un archivo de inicio adicional desde el directorio actual, "
165+
"podés programarlo en el archivo de inicio global usando algo como ``if "
166+
"os.path.isfile('.pythonrc.py'): exec(open('.pythonrc.py').read())``. Si "
167+
"querés usar el archivo de inicio en un script, tenés que hacer lo siguiente "
168+
"de forma explícita en el script::"
120169

121170
#: ../Doc/tutorial/appendix.rst:102
122171
msgid "The Customization Modules"
123-
msgstr ""
172+
msgstr "Los módulos de customización"
124173

125174
#: ../Doc/tutorial/appendix.rst:104
126175
msgid ""
127-
"Python provides two hooks to let you customize it: :mod:`sitecustomize` and :"
128-
"mod:`usercustomize`. To see how it works, you need first to find the "
176+
"Python provides two hooks to let you customize it: :mod:`sitecustomize` and "
177+
":mod:`usercustomize`. To see how it works, you need first to find the "
129178
"location of your user site-packages directory. Start Python and run this "
130179
"code::"
131180
msgstr ""
181+
"Python provee dos formas para customizarlo: :mod:`sitecustomize` y "
182+
":mod:`usercustomize`. Para ver como funciona, necesitás primero encontrar "
183+
"dónde está tu directorio para tu usuario de paquetes del sistema. Arrancá "
184+
"Python y ejecutá el siguiente código::"
132185

133186
#: ../Doc/tutorial/appendix.rst:112
134187
msgid ""
135188
"Now you can create a file named :file:`usercustomize.py` in that directory "
136-
"and put anything you want in it. It will affect every invocation of Python, "
137-
"unless it is started with the :option:`-s` option to disable the automatic "
189+
"and put anything you want in it. It will affect every invocation of Python,"
190+
" unless it is started with the :option:`-s` option to disable the automatic "
138191
"import."
139192
msgstr ""
193+
"Ahora podés crear un archivo llamado :file:`usercustomize.py` en ese "
194+
"directorio y poner lo que quieras en él. Eso afectará cada ejecución de "
195+
"Python, a menos que se arranque con la opción :option:`-s` para deshabilitar"
196+
" esta importación automática."
140197

141198
#: ../Doc/tutorial/appendix.rst:116
142199
msgid ""
143200
":mod:`sitecustomize` works in the same way, but is typically created by an "
144201
"administrator of the computer in the global site-packages directory, and is "
145-
"imported before :mod:`usercustomize`. See the documentation of the :mod:"
146-
"`site` module for more details."
202+
"imported before :mod:`usercustomize`. See the documentation of the "
203+
":mod:`site` module for more details."
147204
msgstr ""
205+
":mod:`sitecustomize` funciona de la misma manera, pero normalmente lo crea "
206+
"el administrador de la computadora en el directorio global de paquetes para "
207+
"el sistema, y se importa antes que :mod:`usercustomize`. Para más detalles, "
208+
"mirá la documentación del módulo :mod:`site`."
148209

149210
#: ../Doc/tutorial/appendix.rst:123
150211
msgid "Footnotes"

0 commit comments

Comments
 (0)