Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilip Withnall <philip@tecnocode.co.uk>2013-09-03 03:07:08 (GMT)
committer Philip Withnall <philip@tecnocode.co.uk>2013-09-03 03:07:08 (GMT)
commitf0679aa34fd9b02f45ddbfb4894373374eaebad7 (patch)
tree248bf8a8d08730f034d68d28981d6652f50321ff
parentf21a2f89cc63ecd92f2d353f9e1d97789f0b3297 (diff)
Finish and translate the part 3 slides and handout
-rw-r--r--.be/dcda61d1-5133-456a-b88c-6bf21e61777b/bugs/b574034a-a16f-43b8-967e-42876dc3c6ef/values2
-rw-r--r--example-ui.pngbin0 -> 24138 bytes
-rw-r--r--example-ui.ui212
-rw-r--r--olpc-square_logo.jpgbin0 -> 28084 bytes
-rw-r--r--slides.tex6
-rw-r--r--writing-sugar-activities.tex1036
6 files changed, 1251 insertions, 5 deletions
diff --git a/.be/dcda61d1-5133-456a-b88c-6bf21e61777b/bugs/b574034a-a16f-43b8-967e-42876dc3c6ef/values b/.be/dcda61d1-5133-456a-b88c-6bf21e61777b/bugs/b574034a-a16f-43b8-967e-42876dc3c6ef/values
index a715bc9..2c4d501 100644
--- a/.be/dcda61d1-5133-456a-b88c-6bf21e61777b/bugs/b574034a-a16f-43b8-967e-42876dc3c6ef/values
+++ b/.be/dcda61d1-5133-456a-b88c-6bf21e61777b/bugs/b574034a-a16f-43b8-967e-42876dc3c6ef/values
@@ -26,7 +26,7 @@
- "status": "open",
+ "status": "fixed",
diff --git a/example-ui.png b/example-ui.png
new file mode 100644
index 0000000..01980d3
--- /dev/null
+++ b/example-ui.png
Binary files differ
diff --git a/example-ui.ui b/example-ui.ui
new file mode 100644
index 0000000..60a7572
--- /dev/null
+++ b/example-ui.ui
@@ -0,0 +1,212 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.6 -->
+ <object class="GtkWindow" id="window1">
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox" id="box2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">8</property>
+ <child>
+ <object class="GtkMenuBar" id="menubar1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkMenuItem" id="menuitem1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_File</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu" id="menu1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem1">
+ <property name="label">gtk-new</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem2">
+ <property name="label">gtk-open</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem3">
+ <property name="label">gtk-save</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem4">
+ <property name="label">gtk-save-as</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkSeparatorMenuItem" id="separatormenuitem1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem5">
+ <property name="label">gtk-quit</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="menuitem2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Edit</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu" id="menu2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem6">
+ <property name="label">gtk-cut</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem7">
+ <property name="label">gtk-copy</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem8">
+ <property name="label">gtk-paste</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem9">
+ <property name="label">gtk-delete</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="menuitem3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_View</property>
+ <property name="use_underline">True</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkMenuItem" id="menuitem4">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">_Help</property>
+ <property name="use_underline">True</property>
+ <child type="submenu">
+ <object class="GtkMenu" id="menu3">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkImageMenuItem" id="imagemenuitem10">
+ <property name="label">gtk-about</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_underline">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="xpad">8</property>
+ <property name="label" translatable="yes">OLPC logo:</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkImage" id="image1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="pixbuf">olpc-square_logo.jpg</property>
+ <property name="icon-size">6</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="button1">
+ <property name="label" translatable="yes">Button</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/olpc-square_logo.jpg b/olpc-square_logo.jpg
new file mode 100644
index 0000000..74bc844
--- /dev/null
+++ b/olpc-square_logo.jpg
Binary files differ
diff --git a/slides.tex b/slides.tex
index 7e6c9bd..d9f5de3 100644
--- a/slides.tex
+++ b/slides.tex
@@ -201,8 +201,8 @@ Windows.}
\mode<all>{\input{python-functions-and-classes}}
-%\part{\en{Writing Sugar activities}\es{Escribir actividades por Sugar}}\label{part:writing-sugar-activities}
-%\frame{\partpage}
-%\mode<all>{\input{writing-sugar-activities}}
+\part{\en{Writing Sugar activities}\es{Escribir actividades por Sugar}}\label{part:writing-sugar-activities}
+\frame{\partpage}
+\mode<all>{\input{writing-sugar-activities}}
\end{document}
diff --git a/writing-sugar-activities.tex b/writing-sugar-activities.tex
index cc42513..59a214c 100644
--- a/writing-sugar-activities.tex
+++ b/writing-sugar-activities.tex
@@ -1,3 +1,1037 @@
\mode* % Reset \mode<all> from slides.tex
-% TODO: This part is yet to be written.
+\section{\en{Overview of Sugar and GTK+}\es{Visión general de Sugar y GTK+}}
+
+\en{The Sugar platform is what runs on the XO. Sugar itself is written in
+Python, but uses a system called GTK+ as its underlying UI toolkit. GTK+ is a
+popular UI toolkit, used by many projects on Linux (not just on the XO).}
+\es{La plataforma de Sugar es lo que se ejecuta en la XO. Sugar sí está escrito
+en Python, pero utiliza un sistema llamado GTK+ como su kit de herramientas de
+interfaz de usuario (IU) subyacente. GTK+ es un popular juego de herramientas de
+interfaz de usuario, que se utiliza por muchos proyectos en Linux (y no sólo en
+la XO).}
+
+\en{Sugar's distinctive appearance is due to a theme it applies to the default
+GTK+ widgets. Without this theme, activities on the XO would look very similar
+to normal Linux programs (such as gedit).}
+\es{El aspecto distintivo de Sugar es debido a un tema que se aplica a los
+widgets GTK+ predeterminados. Sin este tema, las actividades en la XO se vería
+muy similar a los programas normales de Linux (como gedit).}
+
+\en{As with Python, there are two major versions of GTK+ available at the
+moment: GTK+~2 and GTK+~3. GTK+~3 is the recommended version, and is available
+on the XO. All software should be written using GTK+~3 using GIR (GObject
+Introspection) and \emph{not} PyGTK (which is out of date).}
+\es{Al igual que con Python, hay dos versiones principales de GTK+ disponibles
+en este momento: GTK+~2 y GTK+~3. GTK+~3 es la versión recomendada, y está
+disponible en la XO. Todo el software debe ser escrito usando GTK+~3 y GIR
+(introspección GObject) y \emph{no} PyGTK (que es obsoleta).}
+
+\en{Similarly, there are two versions of Sugar code available: \texttt{sugar}
+and \texttt{sugar3}. \texttt{sugar} uses GTK+~2, whereas \texttt{sugar3} uses
+GTK+~3. All new software should be written using \texttt{sugar3}.}
+\es{Del mismo modo, hay dos versiones de código de Sugar disponibles:
+\texttt{sugar} y \texttt{sugar3}. \texttt{sugar} usa GTK+~2, mientras que
+\texttt{sugar3} usa GTK+~3. Todas las novedades software debe ser escrito con
+\texttt{sugar3}.}
+
+\begin{frame}{\en{Sugar and GTK+}\es{Sugar y GTK+}}
+\begin{itemize}
+ \item{\en{All XO activities use Sugar}
+ \es{Todas las actividades XO utilizan Sugar}}
+ \item{\en{Sugar is built on GTK+~3}\es{El Sugar se basa en GTK+~3}}
+ \item{\en{Use \texttt{sugar3} and GTK+~3}
+ \es{Debe utilizar \texttt{sugar3} y GTK+~3}}
+\end{itemize}
+\end{frame}
+
+
+\section{\en{Introduction to GTK+}\es{Introducción a GTK+}}
+
+\en{GTK+ is based on the concept of a hierarchy of \emph{widgets}. A widget is
+a single graphical control, such as a button, some text, a toolbar, or a
+window. These widgets are built into a hierarchy, with child widgets inside
+parent widgets. For example, when a button is shown next to an image, a menu bar
+and a label in a window, this widget hierarchy is used:}
+\es{GTK+ se basa en el concepto de una jerarquía de \emph{widgets}. Un widget es
+un control gráfico único, tal como un botón, un texto, una barra de
+herramientas, o una ventana. Estos widgets están integradas en una jerarquía,
+con widgets hijos dentro de los widgets de los padres. Por ejemplo, cuando se
+muestra un botón al lado de la imagen, una barra de menús y una etiqueta en una
+ventana, se utiliza esta jerarquía de controles:}
+
+\begin{frame}{\en{GTK+ widget hierarchy}\es{Jerarquía de widgets de GTK+}}
+\begin{itemize}
+ \item{\texttt{Gtk.Window}\begin{itemize}
+ \item{\texttt{Gtk.Box}\begin{itemize}
+ \item{\texttt{Gtk.MenuBar}}
+ \item{\texttt{Gtk.Label}}
+ \item{\texttt{Gtk.Image}}
+ \item{\texttt{Gtk.Button}}
+ \end{itemize}}
+ \end{itemize}}
+\end{itemize}
+\end{frame}
+
+\begin{frame}{\en{GTK+ widget hierarchy}\es{Jerarquía de widgets de GTK+}}
+\begin{figure}[h!]
+ \centering
+ \includegraphics[width=0.4\textwidth]{example-ui.png}
+ \caption{\en{The example UI.}
+ \es{Un ejemplo de un IU.}}
+ \label{fig:example-ui}
+\end{figure}
+\end{frame}
+
+\en{Widgets are roughly divided between normal controls and layout containers
+(such as \texttt{Gtk.Box} in the example hierarchy). Other code in GTK+ supports
+key bindings, drag-and-drop and the clipboard.}
+\es{Widgets están divididos más o menos entre los controles normales y
+contenedores de diseño (como \texttt{Gtk.Box} en la jerarquía de ejemplo). Otro
+código en GTK+ soporta atajos de teclado, arrastrar y soltar y el portapapeles.}
+
+\note{Give an interactive demo of Glade and \texttt{example-ui.ui} now.}
+
+\en{\emph{Glade} is a popular tool for building UIs with GTK+. It isn't
+normally used when creating Sugar activities, but is useful for exploring the
+widget hierarchy.}
+\es{\emph{Glade} es una herramienta popular para la creación de IUs con GTK+. No
+se suele utilizar cuando se crean actividades para Sugar, pero es útil para
+explorar la jerarquía de widgets.}
+
+
+\section{\en{Building an interactive UI}\es{Construcción de una IU interactiva}}
+
+\en{To build a UI in GTK+, construct a Python object for each widget, and then
+call methods on the container widgets to add child widgets to parents and thus
+construct a hierarchy.}
+\es{Para construir una IU en GTK+, construir un objeto de Python para cada
+widget, y luego llamar a métodos en los widgets de contenedores para añadir
+hijos a los padres y así la construcción de una jerarquía.}
+
+\begin{frame}[fragile]
+\frametitle{\en{Constructing a GTK+ widget hierarchy}
+ \es{Construcción de una jerarquía de widgets de GTK+}}
+\begin{lstlisting}[language=Python,basicstyle={\ttfamily\footnotesize}]
+from gi.repository import Gtk
+
+window = Gtk.Window(title='Hola Mundo')
+
+# Crear widget contenedor.
+box = Gtk.Box()
+box.set_orientation(Gtk.Orientation.VERTICAL)
+window.add(box)
+# Crear una etiqueta, una imagen y un boton.
+label = Gtk.Label('Logo OLPC:')
+box.add(label)
+image = Gtk.Image()
+image.set_from_file('olpc-square_logo.jpg')
+box.add(image)
+button = Gtk.Button()
+button.set_label('Boton')
+box.add(button)
+
+# Mostrar la IU.
+window.show_all()
+Gtk.main()
+\end{lstlisting}
+\end{frame}
+
+
+\en{In this example, the last two lines of code require explanation. Every GTK+
+widget can be hidden, and all are hidden by default. Before they can be used by
+the user they need to be shown --- either by calling the \texttt{show()} method
+on each widget, or by calling the \texttt{show\_all()} method on one of the
+container widgets which contains them (such as the top-level window, for
+example).}
+\es{En este ejemplo, las dos últimas líneas de código requieren de una
+explicación. Cada widget de GTK+ se puede ocultar, y todos se oculta de manera
+predeterminada. Antes de que puedan ser utilizados por el usuario, es necesario
+que se muestra --- o bien llamando al método \texttt{show()} de cada widget, o
+llamando al método \texttt{show\_all()} en uno de los widgets de contenedor que
+los contiene (como la ventana de nivel superior, por ejemplo).}
+
+\en{The last line of code starts the GTK+ \emph{main loop}. This is what
+handles user input and drawing of widgets in a UI. The main loop is an infinite
+loop which:}
+\es{La última línea de código se inicia el \emph{bucle principal} de GTK+. Esto
+es lo que se encarga de la entrada del usuario y el dibujo de widgets en una IU.
+El bucle principal es un bucle infinito que:}
+
+\begin{frame}{\en{GTK+ main loop}\es{Bucle principal de GTK+}}
+\begin{enumerate}
+ \item{\en{Receives input events from the user (such as mouse movements or
+ keyboard button presses)}
+ \es{Recibe los eventos de entrada del usuario (por ejemplo, los
+ movimientos del ratón o pulsaciones de botones del teclado)}}
+ \item{\en{Calls \emph{event handlers} for those events}
+ \es{Llamadas \emph{controladores de eventos} para los eventos}}
+ \item{\en{Waits for the next input event, then loops}
+ \es{Espera a que el próximo evento de entrada, entonces se realiza un
+ bucle}}
+\end{enumerate}
+\end{frame}
+% TODO: Diagram of the main loop?
+
+\en{This is a standard event-based programming model. It means that after
+calling the \texttt{Gtk.main()} function, all code in your program is executed
+inside callbacks from this main loop. A callback is where the main loop calls
+a function provided by your code: the main loop \emph{calls back} to your
+code.}
+\es{Este es un modelo de programación estándar basado en eventos. Esto significa
+que después de llamar a la función \texttt{Gtk.main()}, todo el código de su
+programa se ejecuta dentro de callbacks de este bucle principal. Un callback es
+donde el bucle principal llama a una función proporcionada por su código: el
+bucle principal \emph{vuelve a llamar} a su código.}
+
+
+\section{\en{Signal handling}\es{Manejo de señales}}
+
+\en{Almost all callbacks in GTK+ are for \emph{signals} from widgets. These
+correspond to events on the widgets. For example, the \texttt{Button} widget
+emits a \texttt{clicked} signal when the user clicks it. Zero or more callbacks
+can be \emph{connected} for this signal, all of which will be called from the
+main loop when the button is clicked.}
+\es{Casi todas las callbacks en GTK+ son para señales de widgets. Estos
+corresponden a eventos en los widgets. Por ejemplo, el widget \texttt{Button}
+emite una señal de \texttt{clicked} cuando el usuario hace clic en él. Cero o
+más callbacks se pueden conectar a esta señal, todos los cuales serán llamados
+desde el bucle principal cuando se hace clic en el botón.}
+
+\en{A signal handler can be connected by calling the \texttt{connect()} method,
+passing the name of the signal, and the name of the function to use as a
+callback. This function must accept the parameters specified in the
+documentation for the signal. It is common practice (though not required) to
+suffix callback function names with \texttt{\_cb} (which stands for
+`callback').}
+\es{Un manejador de la señal se puede conectar mediante una llamada al método
+\texttt{connect()}, pasando el nombre de la señal, y el nombre de la función
+para utilizarla como un callback. Esta función debe aceptar los parámetros
+especificados en la documentación de la señal. Es una práctica común (aunque no
+es obligatorio) a los nombres de funciones callback con sufijo \texttt{\_cb}
+(que significa `callback').}
+
+\en{In this example, we subclass \texttt{Gtk.Window} so that the signal callback
+can be included as a private method of the window. This is a tidy way to do
+things, as it prevents callbacks from different windows getting mixed up.}
+\es{En este ejemplo, subclase \texttt{Gtk.Window} de modo que el callback de la
+señal puede ser incluido como un método privado de la ventana. Esta es una
+manera ordenada de hacer las cosas, ya que evita que callbacks de diferentes
+ventanas se mezclen.}
+
+\begin{frame}[fragile]
+\frametitle{\en{GTK+ signal handlers}\es{Manejadores de señales de GTK+}}
+\begin{lstlisting}[language=Python,basicstyle={\ttfamily\footnotesize}]
+# Subclase Window para crear una ventana.
+class MyWindow(Gtk.Window):
+ def __init__(self):
+ super(MyWindow, self).__init__()
+
+ # Crear y anadir un boton.
+ button = Gtk.Button('Hola Mundo')
+ button.show()
+ self.add(button)
+
+ # Conecte un manejador de senales.
+ button.connect('clicked',
+ self.__button_clicked_cb)
+
+ def __button_clicked_cb(self, button):
+ print('Boton se hizo clic!')
+
+window = MyWindow()
+window.show()
+Gtk.main()
+\end{lstlisting}
+\end{frame}
+
+\en{Signal handling is one of the key features of GTK+, and is worth
+understanding.}
+\es{Manipulación de las señales es una de las características principales de
+GTK+, y vale la pena comprensión.}
+
+\begin{frame}{\en{Signal handling tutorials}\es{Tutoriales sobre el manejo de señales}}
+\begin{itemize}
+ \item{\url{\en{https://developer.gnome.org/gnome-devel-demos/stable/signals-callbacks.py.html.en}
+ \es{https://developer.gnome.org/gnome-devel-demos/stable/signals-callbacks.py.html.es}}}
+ \item{\url{http://python-gtk-3-tutorial.readthedocs.org/en/latest/basics.html\#main-loop-and-signals}}
+\end{itemize}
+\end{frame}
+
+
+\section{\en{GTK+ documentation}\es{Documentación de GTK+}}
+
+\en{GTK+ is a huge library, and covering it in detail here would take too long.
+There are several good tutorials for using GTK+ in Python, available in several
+languages. It is recommended that you read them and practice the exercises they
+give. The \href{https://developer.gnome.org/gtk3/stable/ch03.html}{GTK+ widget
+gallery} contains screenshots of every GTK+ widget, and links to their API
+documentation.}
+\es{GTK+ es una gran librería, y cubriendo en detalle aquí tomaría demasiado
+tiempo. Hay varios buenos tutoriales para el uso de GTK+ en Python, disponible
+en varios idiomas. Se recomienda que los lea y aplique los ejercicios que dan.
+La \href{https://developer.gnome.org/gtk3/stable/ch03.html}{galería de widgets
+de GTK+} contiene imágenes de todos los widgets de GTK+, y enlaces a la
+documentación de la API.}
+
+\begin{frame}{\en{GTK+ tutorials}\es{Tutoriales de GTK+}}
+\begin{itemize}
+ \item{\en{\url{https://developer.gnome.org/gnome-devel-demos/stable/tutorial.py.html.en}}
+ \es{\url{https://developer.gnome.org/gnome-devel-demos/stable/tutorial.py.html.es}}}
+ \item{\en{\url{https://developer.gnome.org/gnome-devel-demos/stable/beginner.py.html.en}}
+ \es{\url{https://developer.gnome.org/gnome-devel-demos/stable/beginner.py.html.es}}}
+ \item{\url{http://python-gtk-3-tutorial.readthedocs.org/en/latest/index.html}}
+ \item{\url{https://developer.gnome.org/gtk3/stable/ch03.html}}
+\end{itemize}
+\end{frame}
+
+\en{The GTK+ API documentation is currently only available for the C
+programming language. However, converting function names between C and Python
+is fairly simple, so you can use the C API documentation for Python.}
+\es{La documentación del API de GTK+ sólo está disponible para el lenguaje de
+programación C. Sin embargo, la conversión de nombres de funciones entre C y
+Python es bastante simple, por lo que puede utilizar la documentación de la API
+C con Python.}
+
+\en{To convert a C function name to a Python method name, remove underscores,
+change it to camelcase, and separate `gtk', the class name, and the method
+name. Python constructors become \texttt{*\_new()} functions in C. Constant
+values are entirely capitalised in C, and only partially capitalised in
+Python.}
+\es{Para convertir un nombre de función C para un nombre de método Python,
+retire subrayado, cambiar a CamelCase, y separado `gtk' del nombre de la clase y
+del nombre del método. Constructores Python vuelven funciones \texttt{*\_new()}
+en C. Valores constantes están completamente activados en C, y sólo parcialmente
+capitalizado en Python.}
+
+\begin{frame}{\en{GTK+ API documentation}\es{Documentación de la API de GTK+}}
+\begin{block}{}
+\url{https://developer.gnome.org/gtk3/stable/gtkobjects.html}
+\end{block}
+\begin{block}{\en{Conversion}\es{Conversión}}
+{\small\begin{align*}
+ \mathbf{Python} &\leftrightarrow \mathbf{C} \\
+ \mathtt{Gtk.Window.set\_title()} &\leftrightarrow
+ \mathtt{gtk\_window\_set\_title()} \\
+ \mathtt{Gtk.Button()} &\leftrightarrow \mathtt{gtk\_button\_new()} \\
+ \mathtt{Gtk.ToggleButton.get\_active()} &\leftrightarrow
+ \mathtt{gtk\_toggle\_button\_get\_active()} \\
+ \mathtt{Gtk.Orientation.VERTICAL} &\leftrightarrow
+ \mathtt{GTK\_ORIENTATION\_VERTICAL}
+\end{align*}}
+\end{block}
+\end{frame}
+
+
+\section{\en{Writing an activity}\es{Escribir una actividad}}
+
+\en{Fundamentally, a Sugar activity is a GTK+ application which provides a
+single GTK+ \texttt{Window} widget for the activity to use. This window forms
+the root of the activity's widget hierarchy, just as in a normal GTK+
+application. Events and callbacks are handled similarly.}
+\es{Fundamentalmente, una actividad de Sugar es una aplicación de GTK+ que
+proporciona un solo widget \texttt{Window} de GTK+ para la actividad de usar.
+Esta ventana se forma la raíz de la jerarquía de widgets de la actividad, al
+igual que en una aplicación normal de GTK+. Eventos y callbacks se manejan de
+manera similar.}
+
+\en{To create an activity, subclass the
+\texttt{sugar3.activity.activity.Activity} class
+in Python. This \texttt{Activity} class provides a method to parent your
+activity's widget tree: \texttt{set\_canvas()}. By creating a widget hierarchy
+and passing it to this function, the interface for an activity can be created.}
+\es{Para crear una actividad, debe subclase de la clase
+\texttt{sugar3.activity.activity.Activity} en Python. Esta clase
+\texttt{Activity} proporciona un método para adjuntar la jerarquía de widgets de
+su actividad: \texttt{set\_canvas()}. Mediante la creación de una jerarquía de
+widgets y pasarlo a esta función, se puede crear la interfaz para una
+actividad.}
+
+\begin{frame}[fragile]
+\frametitle{\en{Creating an activity UI}\es{Creación de una IU de la actividad}}
+\begin{lstlisting}[language=Python,basicstyle={\ttfamily\small}]
+from sugar3.activity import activity
+
+class HolaMundoActivity(activity.Activity):
+ def __init__(self, handle):
+ super(HolaMundoActivity, self).__init__(handle)
+
+ box = Gtk.Box()
+ label = Gtk.Label('Hola Mundo!')
+ button = Gtk.Button('Boton')
+
+ label.show()
+ box.add(label)
+
+ button.show()
+ box.add(button)
+
+ box.show()
+ self.set_canvas(box)
+\end{lstlisting}
+\end{frame}
+
+\en{When subclassing \texttt{sugar3.activity.activity.Activity}, three methods
+must be implemented. \texttt{\_\_init()\_\_} is the normal object constructor,
+and is called when your activity is started by the user. The \texttt{handle}
+parameter provides the activity ID and access to sharing services (which aren't
+covered here).}
+\es{Al crear subclases de \texttt{sugar3.activity.activity.Activity}, tres
+métodos se deben implementar. \texttt{\_\_init\_\_()} es el constructor de
+objeto normal, y se llama cuando su actividad se inicia por el usuario. El
+parámetro \texttt{handle} proporciona el ID de la actividad y el acceso a
+servicios para compartir (que no se cubre en este manual).}
+
+\en{\texttt{read\_file} is called after \texttt{\_\_init\_\_} when resuming an
+activity from the Journal. The \texttt{file\_path} parameter is the path of a
+file containing the saved Journal data. Similarly, \texttt{write\_file} is
+called when the user wants to save the activity to the Journal (either
+explicitly, when closing the activity, or when switching to another activity),
+and the \texttt{file\_path} is the path of a file which the Journal entry
+should be saved to.}
+\es{\texttt{read\_file} es llamada después \texttt{\_\_init\_\_} cuando se
+reanuda la actividad en el Diario. El parámetro \texttt{file\_path} es la ruta
+de un archivo que contiene los datos de diario guardados. Del mismo modo,
+\texttt{write\_file} se llama cuando el usuario desea guardar la actividad con
+el Diario (ya sea de manera explícita, al cerrar la actividad, o cuando se
+cambia a otra actividad), y el \texttt{file\_path} es la ruta de un archivo que
+la entrada de Diario debe ser guardado en.}
+
+\begin{frame}{\en{Required activity methods}
+ \es{Métodos necesarios para actividades}}
+\begin{itemize}
+ \item{\texttt{\_\_init\_\_(self, handle)}}
+ \item{\texttt{read\_file(self, file\_path)}}
+ \item{\texttt{write\_file(self, file\_path)}}
+\end{itemize}
+\end{frame}
+
+\en{The \texttt{Activity} class provides several other methods (apart from
+\texttt{set\_canvas()}) which can be called from within the activity code to
+perform various tasks such as forcing the activity to be saved to the Journal,
+closing the activity, and starting to share the activity on the network. Look
+at the
+\href{https://github.com/sugarlabs/sugar-toolkit-gtk3/blob/master/src/sugar3/activity/activity.py}{source code} for \texttt{sugar3.activity.activity.Activity} for
+details.}
+\es{La clase \texttt{Activity} ofrece varios métodos (además de
+\texttt{set\_canvas()}), que se puede llamar desde dentro del código de
+actividad para realizar diversas tareas, tales como obligar a la actividad que
+se guardan en el Diario, el cierre de la actividad, y empezar a compartir la
+actividad en la red. Mira
+\href{https://github.com/sugarlabs/sugar-toolkit-gtk3/blob/master/src/sugar3/activity/activity.py}{el código} de
+\texttt{sugar3.activity.activity.Activity} para más detalles.}
+
+\en{The most important thing to do in the \texttt{\_\_init\_\_} method is to
+add a toolbar to the activity. Amongst other things, this adds a close button
+to the activity.}
+\es{La cosa más importante que hacer en el método \texttt{\_\_init\_\_} es
+agregar una barra de herramientas a la actividad. Entre otras cosas, esto se
+agrega un botón de cierre de la actividad.}
+
+\begin{frame}[fragile]
+\frametitle{\en{Adding a toolbar}\es{Adición de una barra de herramientas}}
+\begin{lstlisting}[language=Python]
+def __init__(self, handle):
+ # Cree la caja de herramientas de
+ # actividad estandar.
+ toolbar_box = ToolbarBox()
+ self.set_toolbar_box(toolbar_box)
+ toolbar_box.show()
+
+ main_toolbar = toolbar_box.toolbar
+
+ activity_button = widgets.ActivityToolbarButton(self)
+ main_toolbar.insert(activity_button, 0)
+ activity_button.show()
+\end{lstlisting}
+\end{frame}
+
+
+\section{\en{Packaging an activity}\es{Empaquetar una actividad}}
+
+\en{All the files for an activity are bundled together in a special format to
+form a single \texttt{.xo} file which can be executed by the XO. An \texttt{.xo}
+file is just a renamed Zip archive, but it must contain three key files:
+\texttt{setup.py}, \texttt{activity/activity.info} and
+\texttt{activity/activity.svg}.}
+\es{Todos los archivos de una actividad se agrupan en un formato especial para
+formar un único archivo \texttt{.xo} que puede ser ejecutado por el XO. Un
+archivo \texttt{.xo} es sólo un archivo Zip cambiado de nombre, pero debe
+contener tres archivos principales: \texttt{setup.py},
+\texttt{activity/activity.info} y \texttt{activity/activity.svg}.}
+
+\es{Los nombres de archivo en Inglés no se deben traducir al Español, como el
+código de Sugar espera encontrar los nombres de los archivos exactos.}
+
+\begin{frame}{\en{XO bundle format}\es{Formato de los paquetes de XO}}
+\begin{itemize}\item{\texttt{\en{ActivityName.activity}\es{NombreDeActividad.activity}}\begin{itemize}
+ \item{\texttt{\en{activityname.py}\es{nombredeactividad.py}}}
+ \item{\texttt{setup.py}}
+ \item{\texttt{activity/}\begin{itemize}
+ \item{\texttt{activity.info}}
+ \item{\texttt{activity.svg}}
+ \end{itemize}}
+ \item{\texttt{icons/}\begin{itemize}
+ \item{\en{any-custom-icons.svg}\es{los-iconos-personalizados.svg}}
+ \item{$\cdots$}
+ \end{itemize}}
+ \item{\texttt{po/}\begin{itemize}
+ \item{\texttt{de.po}}
+ \item{\texttt{es.po}}
+ \item{\texttt{it.po}}
+ \item{$\cdots$}
+ \item{\texttt{\en{ActivityName.pot}\es{NombreDeActividad.pot}}}
+ \end{itemize}}
+\end{itemize}}\end{itemize}
+\end{frame}
+
+\en{\texttt{activity.info} contains metadata about the activity, such as its
+name, description, ID, version and software licence. \texttt{activity.svg} is
+the icon for the activity. \texttt{setup.py} is used during development to build
+and test the activity, and is the same for all activities.
+\texttt{activityname.py} contains the code for the activity, and can have any
+name --- the actual filename is referenced in \texttt{activity.info}.}
+\es{\texttt{activity.info} contiene metadatos acerca de la actividad, tales como
+su nombre, descripción, ID, la versión y licencia de software.
+\texttt{activity.svg} es el icono de la actividad. \texttt{setup.py} se utiliza
+durante el desarrollo para construir y probar la actividad, y es el mismo para
+todas las actividades. \texttt{nombredeactividad.py} contiene el código para la
+actividad, y puede tener cualquier nombre --- el nombre de archivo real se hace
+referencia en la \texttt{activity.info}.}
+
+% TODO: Add a lstdefinelanguage for this if I get time.
+\begin{frame}[fragile]
+\frametitle{\texttt{activity.info}}
+\begin{lstlisting}
+[Activity]
+name = Pascal Triangle
+summary = Addition game using Pascal's triangle.
+activity_version = 1
+host_version = 1
+bundle_id = hn.educatrachos.pascaltriangle
+icon = activity
+exec = sugar-activity pascaltriangle.PascalTriangleActivity
+license = GPLv2+
+\end{lstlisting}
+\end{frame}
+
+\begin{frame}[fragile]
+\frametitle{\texttt{setup.py}}
+\begin{lstlisting}[language=Python]
+#!/usr/bin/env python
+from sugar.activity import bundlebuilder
+if __name__ == "__main__":
+ bundlebuilder.start()
+\end{lstlisting}
+\end{frame}
+
+\en{The \texttt{icons} directory is optional, and contains any custom icons
+which your activity uses (for example, in toolbars). The XO ships a few standard
+icons, but not many, so activities have to provide their own in many cases.}
+\es{El directorio \texttt{icons} es opcional, y contiene los iconos
+personalizados que utiliza su actividad (por ejemplo, en las barras de
+herramientas). La XO proporciona unos iconos estándar, pero no muchos, por lo
+que las actividades tienen que proporcionar su propia en muchos casos.}
+
+\en{The \texttt{po} directory is also optional (though highly recommended) and
+contains translations of all the UI strings in the activity, so it can be run
+in other languages. By convention, all UI strings in Python are written in
+English --- so when writing an activity, you need to provide a Spanish
+translation as \texttt{es.po}. \texttt{ActivityName.pot} is a template for the
+\texttt{.po} files. Internationalisation will be covered in more detail later.}
+\es{El directorio \texttt{po} también es opcional (aunque muy recomendable) y
+contiene las traducciones de todas las cadenas de la IU en la actividad, por lo
+que se puede ejecutar en otros idiomas. Por convención, todas las cadenas de la
+IU en Python están escritos en Inglés --- así cuando se escribe una actividad,
+es necesario proporcionar una traducción al Español como \texttt{es.po}.
+\texttt{NombreDeActividad.pot} es una plantilla para los archivos \texttt{.po}.
+Internacionalización se explica con más detalle más adelante.}
+
+
+\section{\en{Version control}\es{Control de versiones}}
+
+\en{Creating a new activity starts with creating the directory structure for it,
+then by setting up version control. Version control is a way of cataloguing the
+history of development of some code by storing multiple \emph{revisions} of each
+file. This allows examination of the changes between each revision (as the
+software is developed), and also allows the code to be reverted to a previous
+revision if problems are found in later code. Importantly, version control
+systems make it easy to distribute code across the Internet, by \emph{pushing}
+it to remote repositories.}
+\es{Crear una nueva actividad se inicia con la creación de la estructura de
+directorios para que, a continuación, mediante el establecimiento de control de
+versiones. El control de versiones es una manera de catalogar la historia del
+desarrollo de un código mediante el almacenamiento de múltiples
+\emph{revisiones} de cada archivo. Esto permite que el examen de los cambios
+entre cada revisión (como se desarrolla el software), y también permite que el
+código para revertir a una revisión anterior si los problemas se encuentran en
+el código más adelante. Es importante destacar que los sistemas de control de
+versiones facilitan la distribución del código a través de Internet,
+\emph{empujándolo} a los repositorios remotos.}
+
+\en{The recommended version control system for use with Sugar activities is
+`git', a popular system used by many open source projects. There isn't
+time to give a full introduction to git here, so only a few commands
+will be demonstrated.}
+\es{El sistema de control de versiones se recomienda su uso en las actividades
+de Sugar es `git', un sistema popular y utilizado por muchos proyectos de
+software libre. No hay tiempo para dar una introducción completa a git aquí, así
+que sólo unos pocos comandos se demostrarán.}
+
+\en{Executed from a terminal, in the activity's directory, \texttt{git~init}
+creates a new git repository. (This only needs to be perfomed once.)
+\texttt{git~add} adds files to git's list of staged files, which can be seen by
+running \texttt{git~status}. \texttt{git~commit} creates a new revision in the
+repository, with the changes which were staged using \texttt{git~add}. The whole
+repository can then be pushed to a server. \texttt{git~log} shows the existing
+revisions in the repository.}
+\es{Ejecutado desde un terminal, en el directorio de la actividad,
+\texttt{git~init} crea un nuevo repositorio de git. (Necesario sólo una vez.)
+\texttt{git~add} agrega archivos a la lista de archivos de git organizaron, que
+se puede ver mediante la ejecución de \texttt{git~status}. \texttt{git~commit}
+crea una nueva revisión en el repositorio, con los cambios que se organizaron
+con \texttt{git~add}. Todo el repositorio puede entonces ser empujada a un
+servidor. \texttt{git~log} muestra las revisiones existentes en el repositorio.}
+
+\begin{frame}{\en{Introduction to git}\es{Introducción a git}}
+\begin{itemize}
+ \item{\texttt{git~init}}
+ \item{\texttt{git~add \en{file1.py file2.py}\es{archivo1.py archivo2.py} \dots}}
+ \item{\texttt{git~status}}
+ \item{\texttt{git~commit}}
+ \item{\texttt{git~log}}
+\end{itemize}
+\end{frame}
+
+\begin{frame}{\en{git resources}\es{Recursos para git}}
+\begin{block}{\en{Introductions}\es{Introducciones}}
+\begin{itemize}
+ \item{\url{http://try.github.io/}}
+ \item{\url{http://gitimmersion.com/}}
+\end{itemize}
+\end{block}
+\begin{block}{\en{References}\es{Referencias}}
+\begin{itemize}
+ \item{\url{http://git-scm.com/book\es{/es}}}
+ \item{\url{http://gitref.org/}}
+\end{itemize}
+\end{block}
+\end{frame}
+
+
+\en{Building the XO bundle is achieved using \texttt{setup.py}. When developing
+locally, run \texttt{./setup.py~dev} from a terminal in the activity's directory
+to set up the activity to run on your computer with \texttt{sugar-emulator}
+(discussed later). To build the \texttt{.xo} file for distribution, run
+\texttt{./setup.py~dist\_xo}. When building the \texttt{.xo} file, the script
+will ignore files which aren't committed to git, so ensure all relevant files
+(but not files which have been automatically generated) have been added to git
+using \texttt{git~add}.}
+\es{Construyendo el paquete XO se consigue utilizando \texttt{setup.py}. En el
+desarrollo a nivel local, ejecute \texttt{./setup.py~dev} desde un terminal en
+el directorio de la actividad para establecer la actividad se ejecute en su
+equipo con \texttt{sugar-emulator} (explicado más adelante). Para generar el
+archivo \texttt{.xo} para la distribución, ejecute \texttt{./setup.py~dist\_xo}.
+Cuando se construye el fichero \texttt{.xo}, el script pasará por alto los
+archivos que no se han añadido a git, para asegurar que todos los archivos
+relevantes (pero no los archivos que se han generado de forma automática), se
+han añadido git utilizando \texttt{git~add}.}
+
+\begin{frame}{\texttt{setup.py}}
+\begin{itemize}
+ \item{\texttt{./setup.py~dev}}
+ \item{\texttt{./setup.py~dist\_xo}}
+\end{itemize}
+\end{frame}
+
+
+\section{\en{Emulating Sugar for testing}\es{Emulando Sugar para probar}}
+
+\en{A recommended way to develop activities is to use \texttt{sugar-emulator},
+a program which can be installed on most desktop Linux distributions. It allows
+the Sugar environment to be emulated on a desktop, meaning a new activity can
+be tested without being copied over to a physical XO.}
+\es{Una forma recomendada para el desarrollo de actividades es utilizar
+\texttt{sugar-emulator}, un programa que se puede instalar en la mayoría de las
+distribuciones de Linux. Permite el entorno azúcar a emular en un escritorio, lo
+que significa una nueva actividad puede ser probado sin copiarse a un XO
+físico.}
+
+\en{To run \texttt{sugar-emulator}, simply type its name into the terminal. For
+extra debugging output, also set the \texttt{SUGAR\_LOG\_LEVEL} environment
+variable. To run the emulator in a different language, set the \texttt{LANG}
+environment variable.}
+\es{Para ejecutar \texttt{sugar-emulator}, simplemente escriba su nombre en el
+terminal. Para la salida de depuración extra, también establezca la variable de
+entorno \texttt{SUGAR\_LOG\_LEVEL}. Para ejecutar el emulador en un idioma
+diferente, establezca la variable de entorno \texttt{LANG}.}
+
+\begin{frame}{\texttt{sugar-emulator}}
+\begin{itemize}
+ \item{\texttt{sugar-emulator}}
+ \item{\texttt{SUGAR\_LOG\_LEVEL=debug LANG=es sugar-emulator}}
+\end{itemize}
+\end{frame}
+
+\note{Give an interactive demo of \texttt{sugar-emulator} at this point.}
+
+
+\en{Debugging an activity is similar to debugging any other Python program: the
+simplest way is to use the \texttt{print()} function to print out values from
+the program, and manually check whether they're what's expected --- or whether
+those points in the program are reached at all.}
+\es{Depuración de la actividad es similar a depurar cualquier otro programa de
+Python: la forma más sencilla es utilizar la función \texttt{print()} para
+imprimir los valores del programa, y comprobar manualmente si son lo que se
+espera --- o si esos puntos en el programa se alcanzan en absoluto.}
+
+\en{When using \texttt{sugar-emulator}, text outputted using \texttt{print()}
+won't appear in the normal terminal. Instead, it is saved to a log file in
+\texttt{\textasciitilde/.sugar/default/logs} which is specific to the activity.
+A new log file is created every time the activity is run in a single
+\texttt{sugar-emulator} session, so the number $N$ changes.}
+\es{Al usar \texttt{sugar-emulator}, texto emite utilizando \texttt{print()} no
+aparecerá en el terminal normal. En su lugar, se guarda en un archivo de
+registro en \texttt{\textasciitilde/.sugar/default/logs}, que es específica de
+la actividad. Un nuevo archivo de registro se crea cada vez que la actividad se
+ejecuta en una sola sesión de \texttt{sugar-emulator}, por lo que los cambios en
+el número $N$.}
+
+\en{For a more flexible logging solution which doesn't have to be removed before
+publishing the activity, use the
+\href{http://docs.python.org/2/library/logging.html}{Python \texttt{logging}
+module}. Create a \texttt{logger} object and call methods on it to print
+messages with different severities.}
+\es{Para una solución de registro más flexible que no tiene que ser removido
+antes de la publicación de la actividad, el uso del
+\href{http://docs.python.org/2/library/logging.html}{módulo \texttt{logging} de
+Python}. Crear un objeto \texttt{logger} y llamar a métodos en él para imprimir
+mensajes con diferentes niveles de gravedad.}
+
+\begin{frame}[fragile]
+\frametitle{\en{Sugar logging}\es{Registro en Sugar}}
+\begin{block}{\en{Log files}\es{Archivos de registro}}
+{\large{\texttt{\textasciitilde/.sugar/default/logs/\en{activity.id}\es{actividad.id}-$N$.log}}}
+\end{block}
+\begin{block}{\en{Logging code}\es{Código de registro}}
+\begin{lstlisting}[language=Python]
+import logging
+
+self._logger = logging.getLogger('nombre-de-mi-actividad')
+
+self._logger.error('Este es un error')
+self._logger.warning('...una advertencia')
+self._logger.debug('...un mensaje de depuracion')
+\end{lstlisting}
+\end{block}
+\end{frame}
+
+
+\section{\en{Internationalisation}\es{Internationalisation}}
+
+\en{Internationalisation is an important part of writing an activity, as it
+allows your activity to be used in other languages. Internationalisation is
+mostly about translation, but other things must be considered (such as
+currencies, date formats, and whether text is written left-to-right or
+right-to-left). Adding translation support to an activity is easier; the others
+are more complex and are not covered here.}
+\es{La internacionalización es una parte importante de la escritura una
+actividad, ya que permite que la actividad que se utilizará en otros idiomas. La
+internacionalización es sobre todo acerca de la traducción, pero otras cosas se
+debe considerar (como monedas, formatos de fecha y si el texto se escribe de
+izquierda a derecha o de derecha a izquierda). Adición de apoyo a la traducción
+de una actividad es más fácil; los otros son más complejos y no están cubiertos
+aquí.}
+
+\en{To add translation support, a library called \texttt{gettext} is used. For
+each UI string to be translated, the English string is passed through the
+\texttt{\_} (underscore) function provided by \texttt{gettext}, which returns
+either a translated version, or the original string if no translation is
+available.}
+\es{Para añadir soporte de traducción, se utiliza una librería llamada
+\texttt{gettext}. Para cada cadena de IU sea traducida, la cadena de Inglés se
+pasa a través de la función \texttt{\_} (guión bajo) proporcionado por
+\texttt{gettext}, que devuelve una versión traducida, o la cadena original si no
+hay traducción disponible.}
+
+\begin{frame}[fragile]
+\frametitle{\en{Translation support}\es{Apoyo a la traducción}}
+\begin{lstlisting}[language=Python]
+from gettext import gettext as _
+
+# Previoso: Gtk.Button('Hello world!')
+button = Gtk.Button(_('Hello world!'))
+\end{lstlisting}
+\end{frame}
+
+\en{In addition to these code changes, a set of \texttt{.po} translation files
+have to be created. These give the translations of the English strings into
+other languages, one file per language. Each file is written manually by a human
+translator, working from a \texttt{.pot} template file. This \texttt{.pot} file
+must be periodically updated to reflect changes in the strings marked for
+translation in the program code.}
+\es{Además de estos cambios en el código, un conjunto de archivos de traducción
+\texttt{.po} tienen que ser creados. Estos dan las traducciones de las cadenas
+en Inglés a otros idiomas, un archivo por cada idioma. Cada archivo se escribe
+manualmente por un traductor humano, trabajando desde un archivo de plantilla
+\texttt{.pot}. Este archivo \texttt{.pot} debe actualizarse periódicamente para
+reflejar los cambios en las cuerdas marcadas para la traducción en el código del
+programa.}
+
+\en{To generate the \texttt{.pot} file, run \texttt{./setup.py~genpot}. You can
+then copy the \texttt{.pot} file to (for example) \texttt{es.po} and write the
+Spanish translation. Don't forget to commit both files to git.}
+\es{Para generar el archivo \texttt{.pot}, ejecutar \texttt{./setup.py~genpot}.
+A continuación, puede copiar el archivo \texttt{.pot} a (por ejemplo)
+\texttt{es.po} y escribir la traducción en Español. No te olvides de añadir los
+dos archivos a git.}
+
+\begin{frame}{\en{Generating a POT}\es{Generación de un POT}}
+\begin{itemize}
+ \item{\texttt{./setup.py genpot}}
+ \item{\texttt{cd po}}
+ \item{\texttt{cp \en{ActivityName}\es{NombreDeActividad}.pot es.po}}
+ \item{\en{Edit \texttt{es.po} to create the Spanish translation.}
+ \es{Editar \texttt{es.po} para crear la traducción en Español}}
+\end{itemize}
+\end{frame}
+
+\note{Give an interactive example of generating a POT file and changing it to a
+PO file now.}
+
+\en{Activities whose source code is hosted on \url{http://git.sugarlabs.org} can
+use a web-based service called Pootle to get translations from teams all over
+the world. This is a valuable service, and more information about setting it up
+is available online.}
+\es{Actividades cuyo código está alojado en \url{http://git.sugarlabs.org}
+pueden utilizar un servicio basado en web llamado Pootle para obtener
+traducciones de los equipos de todo el mundo. Este es un servicio valioso, y más
+información sobre su puesta en marcha está disponible en línea.}
+
+\begin{frame}{\en{Adding Pootle support}\es{Añadir soporte de Pootle}}
+\begin{block}{\en{Reference}\es{Referencía}}
+\en{\url{http://en.flossmanuals.net/make-your-own-sugar-activities/going-international-with-pootle/}}
+\es{\url{http://en.flossmanuals.net/como-hacer-una-actividad-sugar/internacionalizarse-con-pootle-god-100/}}
+\end{block}
+\begin{block}{\en{Overview}\es{Visión de conjunto}}
+\begin{enumerate}
+ \item{\en{Push activity code to git.sugarlabs.org, as described below.}
+ \es{Empuje código de actividad a git.sugarlabs.org, tal como se
+ describe a continuación.}}
+ \item{\en{Allow the `pootle' user to commit to git.}
+ \es{Permitir que el usuario `pootle' para crear commites en git.}}
+ \item{\en{File a bug report requesting Pootle support for your project.}
+ \es{Presentar un informe de error solicitando apoyo Pootle para su
+ proyecto.}}
+\end{enumerate}
+\end{block}
+\end{frame}
+
+
+\section{\en{Publishing an activity}\es{Publicar una actividad}}
+
+\en{After finishing the activity, testing it on relevant versions of the XO (in
+emulation and on physical machines), and generating a \texttt{.xo} bundle, the
+activity needs to be published to \url{http://activities.sugarlabs.org} for
+users to download.}
+\es{Después de terminar la escritura de la actividad, la probación en las
+versiones pertinentes de la XO (en la emulación y en máquinas físicas), y la
+generación de un paquete de \texttt{.xo}, la actividad tiene que ser publicada a
+\url{http://activities.sugarlabs.org/es-ES/} para que los usuarios descargar.}
+
+\en{Before publishing the activity, its source code must be made available on
+\url{http://git.sugarlabs.org} so that others can view it and improve on it.
+Educatrachos has \href{https://git.sugarlabs.org/+educatrachos}{a team page} on
+that website, and anyone from Educatrachos who is writing an activity should
+become a member of the team. An administrator (like me) can do that.}
+\es{Antes de la publicación de la actividad, su código debe estar disponible en
+\url{http://git.sugarlabs.org} para que otros puedan verlo y mejorar en él.
+Educatrachos tiene
+\href{https://git.sugarlabs.org/+educatrachos}{una página del equipo} en ese
+sitio web, y cualquier persona de Educatrachos que está escribiendo una
+actividad debe convertirse en un miembro del equipo. Un administrador (como yo)
+puede hacer eso.}
+
+\en{To add an activity to \url{http://git.sugarlabs.org}, add a new project for
+it, then create a repository in that project. Name both after the activity. Once
+the repository's been created, add it as a \texttt{remote} called
+\texttt{origin} in your local git repository, then push the \texttt{master}
+branch to it. Whenever you commit to the local repository from that point
+onwards, you must subsequently push the commit to the remote so that it is
+visible online.}
+\es{Para añadir una actividad a \url{http://git.sugarlabs.org}, agregue un nuevo
+proyecto para que, a continuación, crear un repositorio en ese proyecto. Nombra
+dos después de la actividad. Después ha creado el repositorio, añadirlo como el
+\texttt{remote} se llama \texttt{origin} en su repositorio git local, empujar la
+rama \texttt{master} a ella. Cada vez que se crea un commit en el repositorio
+local de ese punto en adelante, debe posteriormente empujar el commit con el
+mando a distancia para que sea visible en Internet.}
+
+\begin{frame}{\en{Publishing activity source code}
+ \es{Publicación del código de una actividad}}
+\begin{enumerate}
+ \item{\en{Register on \href{http://git.sugarlabs.org}{git.sugarlabs.org}:}
+ \es{Registrarse en
+ \href{http://git.sugarlabs.org}{git.sugarlabs.org}:}
+ \url{https://git.sugarlabs.org/users/new}}
+ \item{\en{Have your account added to the Educatrachos team:}
+ \es{Haga que su cuenta agregada al equipo Educatrachos:}
+ \url{https://git.sugarlabs.org/+educatrachos/memberships/new}}
+ \item{\en{Create a new project owned by the Educatrachos team:}
+ \es{Crear un nuevo proyecto de propiedad del equipo Educatrachos:}
+ \url{https://git.sugarlabs.org/projects/new}}
+ \item{\en{Add a new repository to the project. Enable merge requests so
+ others can suggest changes to the code.}
+ \es{Añadir un nuevo repositorio para el proyecto. Permitir solicitudes
+ de fusiones para que otros pueden sugerir cambios en el código.}}
+ \item{\en{Copy the `SSH' URI from ``Clone \& push URLs'' on the repository
+ page. e.g.\ \url{gitorious@git.sugarlabs.org:pascal-triangle/pascal-triangle.git}}
+ \es{Copie el URI `SSH' desde ``Clone \& push URLs'' en la página del
+ repositorio. Por ejemplo,
+ \url{gitorious@git.sugarlabs.org:pascal-triangle/pascal-triangle.git}}}
+ \item{\en{In a terminal:}\es{En un terminal:}
+ \texttt{cd \en{path/to/my-activity}\es{camino/a/mi-actividad}}}
+ \item{\texttt{git~remote add origin \emph{SSH URI}}}
+ \item{\texttt{git~push -u origin master}}
+\end{enumerate}
+\end{frame}
+
+\en{With the source code published online, the activity can be added to
+\url{http://activities.sugarlabs.org}. You must register an account on that
+website, then join the
+\href{http://activities.sugarlabs.org/en-US/developers}{Developer Hub} and follow
+the process to submit a new activity.}
+\es{Con el código fuente publicada en línea, la actividad se puede añadir a
+\url{http://activities.sugarlabs.org/es-ES/}. Debe registrar una cuenta en ese
+sitio web, y luego unirse el Centro de Desarrollo y seguir el proceso para
+enviar una nueva actividad.}
+
+\en{Newly submitted activities are initially marked as private. Once enough
+details have been filled out for an activity, it is moved to the sandbox, when
+users can start downloading it. Once enough users have downloaded and rated the
+activity, it can be peer-reviewed and promoted to public status.}
+\es{Actividades recién enviados inicialmente se marcan como privados. Una vez
+que suficientes detalles se han llenado de una actividad, se trasladó a la caja
+de arena, cuando los usuarios pueden empezar a descargarlo. Una vez que
+suficientes usuarios han descargado y evaluado la actividad, puede ser revisada
+por pares y promovido a la condición pública.}
+
+\begin{frame}{\en{Publishing an activity bundle}
+ \es{Publicación de un paquete de una actividad}}
+\begin{enumerate}
+ \item{\en{Register on
+ \href{http://activities.sugarlabs.org}{activities.sugarlabs.org}:
+ \url{http://activities.sugarlabs.org/en-US/sugar/users/register}}
+ \es{Registrarse en:
+ \href{http://activities.sugarlabs.org/es-ES/}
+ {activities.sugarlabs.org}:
+ \url{http://activities.sugarlabs.org/es-ES/sugar/users/register}}}
+ \item{\en{Join the `Developer Hub':
+ \url{http://activities.sugarlabs.org/en-US/developers}}
+ \es{Únete a la `Centro de desarrolladores':
+ \url{http://activities.sugarlabs.org/es-ES/developers}}}
+ \item{\en{Follow the process to submit a new activity:
+ \url{http://activities.sugarlabs.org/en-US/developers/addon/submit}}
+ \es{Siga el proceso para enviar una nueva actividad:
+ \url{http://activities.sugarlabs.org/es-ES/developers/addon/submit}}}
+\end{enumerate}
+\end{frame}
+
+
+\section{\en{Conclusion}\es{Conclusión}}
+
+\en{In summary: one of the key aims of writing your own activities should be to
+work in partnership with the worldwide Sugar and OLPC community. This is
+sometimes called ``working upstream''. They are happy to answer questions and
+help solve problems, and in return they would be happy to receive new activities
+and contributions which can be re-used by other OLPC deployments. As with any
+community, the tighter people integrate, the better the results for everyone.}
+\es{En resumen: uno de los objetivos principales de escribir sus propias
+actividades debería ser trabajar en colaboración con la comunidad mundial de
+Sugar y OLPC. Esto a veces se llama ``trabajando río arriba''. Ellos están
+dispuestos a responder preguntas y ayudar a resolver problemas, y en cambio
+estarían felices de recibir las nuevas actividades y las contribuciones que
+pueden ser reutilizados por otros despliegues de OLPC. Al igual que con
+cualquier comunidad, el pueblo más estrictas integran, mejores serán los
+resultados para todos.}
+
+\en{This is the end of the training, but not the end of the learning. I
+encourage you to practice everything you've learned by writing activities. The
+best way to learn programming is through practice. I am happy to answer
+absolutely any questions either in person or by e-mail, even after I've left
+Honduras. I would be thrilled to help get activities published by Educatrachos
+once I return to the UK.}
+\es{Este es el final de la capacitación, pero no el final del aprendizaje. Les
+animo a practicar todo lo que has aprendido al escribir algunas actividades. La
+mejor manera de aprender es a través de la práctica de programación. Estoy
+encantado de responder a cualquier pregunta en absoluto, ya sea en persona o por
+e-mail, incluso después de que me he dejado Honduras. Yo estaría encantado de
+ayudar a que las actividades publicadas por Educatrachos cuando regreso al
+Reino~Unido.}
+
+\note{After a break, it would be a good idea to give an interactive demo of
+creating an entire activity from scratch.}
+
+
+\section{\en{Miscellany}\es{Miscelánea}}
+
+\en{Again, not all the features of Sugar can be covered
+in the available time. Here are the topics which haven't been covered, along
+with links to relevant documentation. Writing activities in HTML5 wasn't covered
+because the version of Sugar deployed in Honduras is too old to support them.}
+\es{Una vez más, no todas las características de Sugar se pueden cubrir en el
+tiempo disponible. Estos son los temas que no han sido cubiertos, así como
+enlaces a la documentación pertinente. Las actividades de escritura en HTML5 no
+estaba cubierto por la versión de Sugar desplegado en Honduras es demasiado
+viejo para apoyarlos.}
+
+\begin{frame}{\en{What's missing}\es{Temas no abarcados}}
+\begin{itemize}
+ \item{\en{Drawing custom widgets with Cairo:}
+ \es{Dibujo widgets personalizados con Cairo:}
+ % FIXME: This should actually be the following, but it doesn't exist yet:
+ % https://developer.gnome.org/gnome-devel-demos/unstable/widget_drawing.py.html.en
+ \href{http://tecnocode.co.uk/misc/platform-demos/widget_drawing.py.xhtml}{(1)},
+ \href{http://www.tortall.net/mu/wiki/CairoTutorial}{(2)},
+ \href{https://sites.google.com/site/randomcodecollections/home/python-gtk-3-pango-cairo-example}{(3)},
+ \href{http://ptomato.name/advanced-gtk-techniques/html/custom-container.html}{(4)},
+ \href{http://lotsofexpression.blogspot.com/2012/04/python-gtk-3-example-implementing-cairo.html}{(5)}}
+ \item{\en{Shared activities:}\es{Actividades compartidas:}
+ \en{\href{http://en.flossmanuals.net/make-your-own-sugar-activities/making-shared-activities/}{(1)}}
+ \es{\href{http://en.flossmanuals.net/como-hacer-una-actividad-sugar/making-shared-activities-vc/}{(1)}}}
+ \item{\en{Text-to-speech:}\es{Texto a voz:}
+ \en{\href{http://en.flossmanuals.net/make-your-own-sugar-activities/adding-text-to-speech/}{(1)}}
+ \es{\href{http://en.flossmanuals.net/como-hacer-una-actividad-sugar/adding-text-to-speach/}{(1)}}}
+ \item{\en{Games with PyGame:}\es{Juegos con PyGame:}
+ \en{\href{http://en.flossmanuals.net/make-your-own-sugar-activities/making-activities-using-pygame/}{(1)}}
+ \es{\href{http://en.flossmanuals.net/como-hacer-una-actividad-sugar/construir-actividades-usando-pygame/}{(1)}}}
+ \item{HTML5:
+ \href{http://developer.sugarlabs.org/web-architecture.md.html}{(1)}}
+\end{itemize}
+\end{frame}
+
+
+\begin{frame}{\en{Links}\es{Enlaces}}
+\begin{block}{\en{Important links}\es{Enlaces importantes}}
+\begin{itemize}
+ \item{\en{\url{http://en.flossmanuals.net/make-your-own-sugar-activities/}}
+ \es{\url{http://en.flossmanuals.net/como-hacer-una-actividad-sugar/heredar-activity-de-sugaractivity-jm-50/}}}
+ \item{\url{http://python-gtk-3-tutorial.readthedocs.org/en/}}
+ \item{\url{http://doc.sugarlabs.org/epydocs/}}
+\end{itemize}
+\end{block}
+\begin{block}{\en{Other links}\es{Enlaces otros}}
+\begin{itemize}
+ \item{\url{http://wiki.sugarlabs.org/go/Features/GTK3/Porting}}
+ \item{\url{http://wiki.sugarlabs.org/go/Human_Interface_Guidelines/The_Sugar_Interface}}
+ \item{\url{http://wiki.sugarlabs.org/go/Development_Team/Almanac}}
+ \item{\url{http://wiki.sugarlabs.org/go/Activity_Team}}
+\end{itemize}
+\end{block}
+\end{frame}
+
+
+\begin{frame}<presentation>{\en{Questions?}\es{¿Preguntas?}}
+\en{Any questions so far?}
+\es{¿Hay preguntas hasta ahora?}
+\end{frame}