martes, marzo 16, 2010

Traduciendo FoodForce

En La Rioja, Jorge Cabrera me contó una idea que me pareció muy buena, modificar el Food Force para adaptarlo a una época de la historia de la provincia. Mientras pensaba como hacerlo, se me ocurrió que sería mejor comenzar por trabajar en la internacionalización (i18n) del juego, y una vez que supieramos bien como funciona y como está programado, sería mas facil modificarlo. A su vez, es un juego interesante para que usen los chicos.
Nos contactamos con Mohit Taneja, uno de los desarrolladores y se mostró interesado en la i18n.
Como puede ser util para otras actividades, detallo aqui el procedimiento aplicado, aunque está bien explicado en http://wiki.laptop.org/go/Internationalization_in_Sugar

Si iniciamos el juego vemos esta pantalla (haciendo click en las imagenes pueden ver mejor los textos)


Para empezar por los textos que se ven en esta pantalla, en primer lugar busco en que archivo del programa se encuentran. Desde el directorio de la actividad (Activities/FoodForce2.activity/) en la linea de comandos escribo:


[gonzalo@nautilus FoodForce2.activity]$ grep -n "Start New Game" *.py
Foodforce2.py:304: self.start_button = gui.Button(position = threades.resize_pos((475,500)), size = threades.resize_pos((250,50)), parent = desktop2, text = "Start New Game",style = self.button_style)


Esto me indica que el texto que busco está en la linea 304 del archivo FoodForce2.py. Ahora lo tenemos que editar con cualquier editor de texto.

Para poder hacer la i18n de ese archivo, debemos agregar al comienzo del archivo, donde estan los imports, una linea que importe la libreria necesaria

import pygame
from pygame.locals import *
from pygame.display import *
from pygame.mouse import *
from gettext import gettext as _


ahora buscamos las lineas donde se encuentran el texto de los botones y reemplazamos el texto, por ejemplo "Start New Game", por _("Start New Game")

En este caso vamos hasta la linea 304 y modificamos para que quede:


if self.pause_flag:
self.start_button = gui.Button(position = threades.resize_pos((475,500)), size = threades.resize_pos((250,50)), parent = desktop2, text = _("Start New Game"),style = self.button_style)
self.start_button.onClick = self.startup_text
if self.init_game_save_flag == True:
self.resume_saved_level_button = gui.Button(position = threades.resize_pos((475,430)),size = threades.resize_pos((250,50)), parent = desktop2, text = _("Resume Saved Game"),style =self.button_style)
self.resume_saved_level_button.onClick = self.resume_saved_level
else:
self.resume_button = gui.Button(position = threades.resize_pos((475,500)), size = threades.resize_pos((250,50)), parent = desktop2, text = _("Resume Game"),style = self.button_style)
self.resume_button.onClick = self.resume
#Save Game Button
if proceduralFlow.storyboard_level != 1:
self.save_button = gui.Button(position = threades.resize_pos((475,430)), size = threades.resize_pos((250,50)), parent = desktop2, text = _("Save Current Level"),style = self.button_style)
self.save_button.onClick = self.save_current_level
self.controls_button = gui.Button(position = threades.resize_pos((475,640)), size = threades.resize_pos((250,50)), parent = desktop2, text = _("Controls"),style = self.button_style)
self.exit_button = gui.Button(position = threades.resize_pos((475,710)), size = threades.resize_pos((250,50)), parent = desktop2, text = _("Exit"),style = self.button_style)
self.instructions_button = gui.Button(position = threades.resize_pos((475,570)), size = threades.resize_pos((250,50)), parent = desktop2, text = _("Guide"),style = self.button_style)
self.about_us_button = gui.Button(position = threades.resize_pos((1000,20)), size = threades.resize_pos((150,40)), parent = desktop2, text = _("About Us"),style = self.button_style)


Ahora, como la actividad no lo incluye, agregamos un archivo setup.py con el siguiente contenido:
from sugar.activity import bundlebuilder
bundlebuilder.start()
y lo ejecutamos:

python setup.py genpot

Esto nos genera el directorio y archivo con las traducciones.
Nos movemos a ese directorio

[gonzalo@nautilus FoodForce2.activity]$ cd po

Y creamos el archivo para las traducciones en español:

[gonzalo@nautilus po]msginit -l es

Me pide mi mail y genera un archivo es.po
Tenemos que editarlo y agregar las traducciones a los textos, en este caso queda:


# Spanish translations for FoodForce package.
# Copyright (C) 2010 THE FoodForce'S COPYRIGHT HOLDER
# This file is distributed under the same license as the FoodForce package.
# Gonzalo Odiard , 2010.
#
msgid ""
msgstr ""
"Project-Id-Version: FoodForce 2.activity\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2010-03-16 00:04-0300\n"
"PO-Revision-Date: 2010-03-16 00:06-0300\n"
"Last-Translator: Gonzalo Odiard \n"
"Language-Team: Spanish\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ASCII\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"

#: activity/activity.info:2
#: /home/gonzalo/Activities/FoodForce2.activity/activity.py:8
msgid "FoodForce2"
msgstr ""

#: /home/gonzalo/Activities/FoodForce2.activity/Foodforce2.py:307
msgid "Start New Game"
msgstr "Comienza Nuevo Juego"

#: /home/gonzalo/Activities/FoodForce2.activity/Foodforce2.py:311
msgid "Resume Saved Game"
msgstr "Retoma Juego Anterior"

#: /home/gonzalo/Activities/FoodForce2.activity/Foodforce2.py:316
msgid "Resume Game"
msgstr "Retoma Juego"

#: /home/gonzalo/Activities/FoodForce2.activity/Foodforce2.py:321
msgid "Save Current Level"
msgstr "Graba Nivel Actual"

#: /home/gonzalo/Activities/FoodForce2.activity/Foodforce2.py:325
msgid "Controls"
msgstr "Controles"

#: /home/gonzalo/Activities/FoodForce2.activity/Foodforce2.py:326
msgid "Exit"
msgstr "Salir"

#: /home/gonzalo/Activities/FoodForce2.activity/Foodforce2.py:327
msgid "Guide"
msgstr "Guia"

#: /home/gonzalo/Activities/FoodForce2.activity/Foodforce2.py:328
msgid "About Us"
msgstr "Acerca de"


Ahora tenemos que preparar el archivo de traducciones compiladas, que usará finalmente la actividad, para ello necesitamos saber el service_name de la actividad, hacemos:


[gonzalo@nautilus po]$ cat ../activity/activity.info
[Activity]
name = FoodForce2
activity_version = 4
host_version = 1
service_name = org.laptop.community.FoodForce2
icon = activity-foodforce2
exec = sugar-activity activity.Activity


Ahora creamos el directorio para las traducciones compiladas


[gonzalo@nautilus po]$ mkdir -p ../locale/es/LC_MESSAGES/


Y creamos el archivo compilado, con el nombre que tomamos del service name:


[gonzalo@nautilus po]$ msgfmt es.po --output='../locale/es/LC_MESSAGES/org.laptop.community.FoodForce2.mo'


Ahora si ingreso en la aplicacion veo:


Bien, este es el comienzo. Segun nos explica Mohit Taneja, la mayoría de los textos se encuentran en los siguientes archivos:

texts.py : These are the texts which are shown at the start and end of the game.

display_panel.py : It contains the texts regarding the resources panel, manpower resources and stuff.

storyboard.pkl : It contains the strings regarding the chats and mission messages being shown in the game. This file is created by write_storyboard.py script. This file is not present in the XO bundle but is present in the svn repository of foodforce2.

gui_buttons.py : this file contains the strings which are displayed when you open windows regarding setup facility, upgrade facility, and buy sell button.

Comenzaremos por los archivos .py y luego veremos como hacemso con el archivo storyboard.pkl

Alguien está interesado en colaborar?

No hay comentarios.: