Localizate, chabón

Uno de los bugs críticos que tenía en Enjuéwemela era el de internacionalizarlo/localizarlo.

Este proceso (que tiene en inglés nombres tan complicados que se los refiere normalmente como i18n y l10n, deduzcan ustedes por qué) básicamente permite al programa mostrar todos los textos en el lenguaje del usuario.

Obviamente, para que todos los textos de un programa estén en varios idiomas, la gente tiene que traducirlos, y aparte el programa tiene que mostrar los textos correspondientes en el lugar adecuado, en función del idioma del usuario. La forma de hacer esto está establecida desde hace varios años, y está armada especialmente para facilitar que colaboradores creen nuevas traducciones y se agreguen al sistema.

Esta tecnología se conoce como Gettext, y se puede utilizar desde todos (o casi todos) los lenguajes existentes. Pero una cosa es utilizarlo, y otra es armar el programa para que pueda utilizarlo, y que se puedan agregar nuevas traducciones, etc.

Recuerdo que cuando lo hice para Typus Pocus no salió fácil, y tuve que leer bastante. Casi me pongo a pensar nuevamente como era, pero se me prendió la lamparita y me acordé que en su momento había escrito en ese proyecto un procedimiento_locale.txt, así que lo tomé y usé.

Para que estos pasos los puedan usar todos, los dejo acá. Pero ojo, no muestran como usar gettext desde tal o cual lenguaje (eso lo verán ustedes), sino cómo preparar los archivos y directorios para que luego puedan usar gettext desde sus programas. Por otro lado, los ejemplos son las lineas que tiré para Enjuéwemela, así que están orientados a Python, sepan adaptar.

Entonces...

Creamos el directorio para guardar nuestra estructura de traducciones:

mkdir locale

Editamos todos nuestros archivos y metemos todos los textos que queramos internacionalizar en la llamada a función _(). O sea, que si teníamos el texto "click here" y queremos que ese texto se internacionalice, tenemos que dejar _("click here"). Esto es vital para el próximo paso, y para el funcionamiento luego, ya que _() será la función de gettext que reemplazará lo que está escrito en el código con lo que se mostrará al usuario en función de su lenguaje.

Generamos el archivo .pot con todos los textos que utilizamos en nuestro programa. Para ello utilizamos xgettext y le pasamos todos los .py que usamos (esta utilidad revisará las fuentes y tomará los textos que tienen el _() que agregamos antes):

xgettext *.py --output=locale/core.pot

Este .pot es el archivo template que distribuiremos a todos aquellos que deseen traducir nuestro programa. Antes de distribuirlo, deberíamos abrirlo con un editor y completar ciertos campos que están listos para ser rellenados (título, autor, etc.).

La preparación propiamente dicha del sistema ya está completa, los pasos a continuación muestran qué hacer con el .pot si queremos generar la traducción para un nuevo lenguaje.

Generamos el .po, renombrando la base del archivo para incorporarle las dos letras del idioma que estamos utilizando. Si es la primera vez, sólo copiamos el .pot al mismo...

cd locale
cp core.pot core_es.po

..., pero si ya teníamos el .po de antes y ahora tenemos un nuevo .pot (porque aparecieron nuevos textos en el programa, o cambiaron los que estaban de antes), tenemos que mergear los archivos de la siguiente manera:

cd locale
msgmerge core_es.po core.pot > /tmp/po_temporal
mv /tmp/po_temporal core_es.po

El próximo paso es abrir el core_es.po con un editor de texto y traducir todas las cadenas. Luego, tenemos que compilar el .po al .mo, que es el archivo que levantará realmente el sistema gettext:

msgfmt core_es.po

Y finalmente, movemos el archivo compilado a un directorio que tiene que seguir la estructura preestablecida aquí mostrada (prestar atención al renombre del archivo en sí, y a que en el directorio está el idioma utilizado en la traducción):

mkdir -p es/LC_MESSAGES
mv messages.mo es/LC_MESSAGES/core.mo

Como último detalle, quiero aclarar que hay muchos editores especializados que muestran los .po y .pot uno al lado del otro, especialmente útiles cuando los programas a traducir son muy grandes o contienen muchos textos, pero que realmente uno se puede arreglar con un editor de textos común y corriente.

Comentarios Imprimir

Linux Week Perú 2010

Fuí gentilmente invitado a dar una charla en dicho evento (EDITADO: la url no existe más), en la Universidad Católica de Lima, Perú.

Llegué el lunes bien tarde, y me volví el sábado al mediodía para Argentina. En el medio esta buena gente me trató más que bien: me sacaron siempre a almorzar/cenar, me llevaron/trajeron a la Universidad, etc. (no solo los organizadores, sino también Nico Valcarcel, compañero de Canonical, que se re portó).

Lamentablemente no pude pasear demasiado por Lima... aunque era la primera vez que iba me quedé sin ver nada más que lo que espié desde taxis y coches, porque tenía que trabajar durante mañana y tarde (el evento era a la noche). Es que era esto o no ir para nada, porque estamos trabajando contra reloj por la liberación de Lucid Lynx y no era momento de tomar días de vacaciones).

Pero la visita me sirvió para conocer a Fernando San Martín, de Chile, que dio una charla muy interesante sobre la importancia de los proyectos de código abierto en la formación profesional, y con el que charlamos muchísimos temas de software y demás (y también de los lamentables sucesos sísmicos acaecidos recientemente en su hogar). También pude conocer y charlar con otras personas de la comunidad peruana, como Rosa María, Marcos, Diego, Antonio, y tantos otros.

Mi presentación fue sobre Python en el mundo real, y la verdad es que salió muy bien (siendo la primera vez que la daba)... la gente no se durmió, se mostró muy interesada, y al terminar hubieron decenas de preguntas, no sólo en el espacio que correspondía, sino afuera del auditorio, y en todo el camino hacia la salida (ya cuando la gente de la Universidad nos echaba porque debían cerrar).

Algunos comentarios sobre Lima:

  • Manejan mal, muy mal. Demasiado rápido, saltando de carril en carril, frenando demasiado cerca de los otros autos, cruzándose a otros que quieren pasar primero, siempre haciendo luces y tocando bocina. Creo que escuché más bocinazos en estos cuatro días que en el resto de mi vida...

  • Hay muchos casinos. Habré visto unos 30 distintos, desde pequeños locales a megacasinos todos iluminados. Según me comentaban, es porque no hay una legislación fuerte al respecto, así que hacen medio lo que quieren.

  • La cocina es buenísima, todo muy rico y no hubo nada que no me haya gustado. Encima, siempre me invitaron a probar muchos platos con mucha variedad... comí más que demasiado (y bebí otro tanto), la verdad, porque estuvo todo muy rico. Ahora ya respiro tranquilo, pero en algún momento pensé que me estaban engordando y que me iban a carnear en el cierre del evento...

Me queda pendiente visitar la ciudad desde un punto de vista más turístico, seguramente volveré en el futuro. Muchas gracias a Rosa María Orellana y todo su equipo de trabajo por este evento.

Comentarios Imprimir

Community Award

Y cuando uno cree que ya nada lo sorprende, va y recibe un premio de la Python Software Foundation!

El premio de Facundo Batista fue por organizar PyCon Argentina y la comunidad argentina de Python, así como también por sus contribuciones a la biblioteca estándar y por su trabajo en traducir la documentación de Python.

¡Estoy tan contento por esto!

:D

Comentarios Imprimir

PyCamp 2010

Viernes

En realidad llegamos a Verónica el jueves. Viajamos a la tarde/noche con Alecu, Ricardo y Joac, para llegar, cenar, acostarnos, y levantarnos temprano para armar lo que era energía e internet.

El plan estuvo muy bien, nos levantamos casi a las ocho, desayunamos, y empezamos a armar todo... para cuando empezó a llegar la gente, ya teníamos todo andando.

La mañana estuvo tranquila, charlando de cosas varias mientras iban llegando los participantes, y recién luego de comer arrancamos con la organización del schedule para todos los días:

Schedule de PyCamp 2010

El primer tema me interesaba (tower defense); no para programarlo, sino para participar en la charla inicial. Las ideas estuvieron muy bien, veamos como evoluciona.

También participé de la segunda sesión (hacer un server XMPP en Twisted), pero llegamos a la conclusión que no tiene sentido ponernos a hacer todo ese trabajo, porque para las funcionalidades locas que quisiéramos implementar, es suficiente con hacer un cliente o un componente (y ya hay soporte para eso en Twisted).

Luego me pegué un regio baño, y llegó la hora de la cena. Y con el fin de la comida, pasamos a la parte de juegos.

Como siempre, se armaron distintos grupos jugando a distintas cosas. Yo jugué al Settlers of Catan con Perrito, Robert, y Luciano. Un rato después de que terminamos de jugar (y de que nos habíamos terminado el Legui), llegó Moni con Felipe, que venían de Buenos Aires en el auto de John, así que fuimos a terminar de armar las cosas en la habitación y a dormir, que eran como las dos de la mañana.

Sábado

Por suerte no arrancamos temprano, ya que el desayuno es a las nueve de la mañana, así que me levanté ocho y media, y a las nueve estábamos desayunando con la familia.

Durante la mañana no hice nada específico, más que nada charlas, cargué muchos bugs de Enjuewemela, y le eché algo de laburo a Typus Pocus: nos fuimos de Google Code, ahora estamos en Launchpad, y empecé a darle forma para poder utilizarlo de ejemplo en la clase de empaquetamiento de Luciano (ver más abajo).

A las 13 almorzamos, y luego jugamos a la pelota como media hora (sí, ¡deporte!). Cortamos a las 14 porque arrancaba la sesión de Lalita. Nos juntamos obviamente al aire libre (estabamos la mitad transpirados por el fúbol), y charlamos cosas para hacerle. Me anoté un bug doble (o dos bugs muy parecidos, como quieran), pero antes de empezar a hacer eso me fui a bañar.

Familia en PyCamp

Cuando salí encontré que ya había empezado la charla de cocos2d, y me metí para la charla/discusión sobre qué era y cual es el futuro (llegamos a la conclusión de que lo que habría que hacerle a la biblioteca es: mejor manejo de sonido, implementar colisiones, mejor documentación, y bugfixing en general).

La noche pintaba tranqui, porque no habíamos podido armar el fogón entonces no sabíamos que íbamos a hacer con la reunión de PyAr. Pero al final la hicimos, repartimos merchandising que Nati y Matías habían traido de USA, repartimos tutoriales impresos para que lleven a las Universidades, hablamos del PyCon en Argentina pasado y futuro, del recién terminado PyCon USA, de Python y la evolución del lenguaje, de cómo estaba Python en Argentina a nivel laboral, etc. Muchos temas. Y terminó derivando en charlas políticas muy interesantes.

A eso de las dos y media de la mañana, luego de charlar en varios grupos y con ya demasiado vino en sangre, me fuí a dormir.

Domingo

El domingo arranqué con un poco de resaca, pero llegué bien a desayunar.

Durante la mañana estuve trabajando en Typus Pocus, para que esté listo para la clase de la tarde de Luciano Bello sobre empaquetar proyectos para Debian. Esa clase fue muy útil, y recorrimos casi todos los pasos para que se pueda meter el juego en esa distro de Linux (todavía faltan sacarle unos warnings de lintian, ya anunciaré aquí como evoluciona eso).

Luego se hizo un pequeño Bug Day de Python, en la cual muchos chicos aprendieron cómo trabajar en el proyecto de Python en sí, y cómo buscar bugs y proponer soluciones, y hasta se corrigieron un par de cosas!

Durante la tarde, también, se realizó el primer Torneo Universal de Ping Pong Durante Un PyCamp (o más fácil: TUPPDUPC). Yo perdí en cuartos a manos de (o "a paletas de") el que sería el campeón, Nico Echaniz:

Torneo de ping pong

Estuvimos también charlando un rato largo sobre el modelo del juego que construiremos durante el próximo PyWeek (el juego más grande del mundo (EDITADO: la url no existe más), ¡ya les contaré cómo participar!).

Finalmente, volví a trabajar en la laptop, en el bug doble de Lalita que había comenzado a resolver el día anterior. Y estando ahí trabajando, al lado de Riq, no se bien cómo surgió pero me terminó explicando cómo se usaban matrices para resolver los cambios a imágenes (redimensionarlas, rotarlas, desplazarlas, etc.; lean esto que lo explica bien).

Lunes

Durante la mañana del último día logré corregir los bugs que venía trabajando de Lalita, antes de comer me puse a trabajar en un juego que estoy armando, Enjuewemela, un juego loco con un montón de gemas que tienden a desaparecer siguiendo extrañamente acciones del usuario.

Luego del almuerzo tuvimos una charla entre todos sobre el PyCamp mismo: cómo había sido, que cosas estuvieron mal, cuales bien, qué deberíamos corregir, y hasta terminamos tirando la idea de hacer un segundo PyCamp a continuación de PyCon Argentina 2010, en Córdoba.

Luego de esta charla seguí trabajando en Enjuewemela, hasta que se acabó el tiempo.

Ahí empecé a ordenar todo lo mío y a limpiar un poco los lugares donde habíamos trabajado, armé el auto, y emprendimos el regreso.

Trabajando

Así terminó el tercer PyCamp en Argentina, uno de los eventos de programación más interesantes que conozco, y uno de los que más cumplen a la hora de aprender y divertirse. Todas las fotos, aquí.

Comentarios Imprimir

Más y más películas.

Hace casi cinco meses que no actualizaba la lista de vistas/anotadas, y por eso se juntó tanto...

Vistas:

  • 88 minutes: +0. Buen ritmo, buen enigma, aunque nada del otro mundo.

  • Alatriste: +1. Buenas actuaciones, buena historia, y muy bien ambientado.

  • Anamorph: +0. Interesante desde un par de puntos de vista, pero nada del otro mundo.

  • Avatar: +1. Buenísima historia, fascinante la producción. Lo real de la "realidad inventada" asusta.

  • Burn after reading: -0. Buenos actores, buenas actuaciones, y una historia mezclada e interesante, pero que no conduce a nada.

  • Cloverfield: -0. Lo único que tiene piola es el manejo de la cámara...

  • Deception: +0. Buena trama, buenas actuaciones, podría tener más consistencia.

  • Eastern promises: +0. Historia simple, pero bien armada, bien llevada.

  • El amor en los tiempos del cólera: +1. Muy buenas actuaciones, y por supuesto la historia no tiene desperdicio.

  • Get smart: +0. Si te gusta o gustó el Superagente 86, no te la podés perder.

  • Hanckok: +1. Es divertida y dinámica, y le da un punto de vista nuevo al concepto de "superhéroe".

  • I am legend: +1. Dinámica y bien armada, muestra un muy posible futuro cercano.

  • Indiana Jones and the kingdom of the Crystal Skull: +1. Indiana Jones como siempre.

  • Martín Fierro, el ave solitaria: +0. La historia es conocida, los dibujos de Fontanarrosa son espectaculares.

  • Michael Clyton: +0. Una buena historia sobre la ética y los valores de una persona en su vida personal y laboral.

  • Star Trek: +1. Dinámica y bien armada, es absolutamente imperdible si te gusta Viaje a las Estrellas.

  • The day the Earth stood still: -0. La idea está buena, pero se podría explorar un poco más serio, y queda demasiado en el sentimentalismo barato.

  • The forbidden kingdom: -1. Pensé que el humor la iba a salvar y quería darle una oportunidad a estas pelis de patadas... me equivoqué.

  • The hunting party: +1 muy buena peli que muestra algunos tejes y manejes atrás de las guerras eternas de medio oriente.

  • The mist: +0. No deja de ser una película de terror más, pero es de un libro de Stephen King, y aparte tiene uno de los finales más duros que ví en una película.

  • The nines: +0. Película muy loca, interesante, pero rara.

  • The notebook: +1. Fantástica historia, presentando dos o tres preguntas que hay que contestarse en la vida.

  • The sentinel: +0. Se nota que es la peli de una novela, porque quedan mil detalles a medio explicar. Más allá de eso es entretenida.

  • Things we lost in the fire: +1. Una historia muy bien contada sobre dos personas que necesitan salir de su pozo en particular. Benicio del Toro, muy bien.

  • Wanted: +1. Acción de la buena, bien armada y contada, con lo justo de misterio.

  • Zeitgeist: +1. Documental en tres partes, imperdible para enterarse de algunas verdades.

Nuevas:

Finalmente, el resumen según cuando las anoté, ya con más historial:

(26-Jan-2007)   1   1
(26-Mar-2007)   7   2
(15-Jun-2007)   4   2
(19-Nov-2007)  14  12   3
(23-May-2008)  25  24  21   4
(24-Sep-2008)  37  34  31  29
(21-Ene-2009)  22  19  19  19
(09-May-2009)      17  16  14
(15-Oct-2009)          21  20
(01-Mar-2010)              19
Total:        113 111 111 105
Comentarios Imprimir