Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





[C++] Usar varios idiomas

Iniciado por Hyruleoflink, 26 de Abril de 2012, 02:28:51 PM

« anterior - próximo »

Hyruleoflink

Buenas!

estoy trabajando en mi primer proyecto personal y quiero incluir la capacidad de permitir al jugador seleccionar el idioma del juego, pero no sé muy bien cómo implementar esto.

Lo estoy implementando con C++ y SDL, y mi primera idea era usar condiciones para mostrar un texto u otro según el idioma seleccionado, pero el código ya está siendo bastante extenso y modificar los diálogos en un futuro se complicaría.

Otra opción que he pensado es tener los dialogos en un fichero y cargarlos durante la ejecución, pero no sé si tantos accesos a fichero podría relantizar el refresco de pantalla.

¿Alguien puede recomendarme algún método eficaz?

Fanakito

Cita de: hyruleoflink en 26 de Abril de 2012, 02:28:51 PMLo estoy implementando con C++ y SDL, y mi primera idea era usar condiciones para mostrar un texto u otro según el idioma seleccionado, pero el código ya está siendo bastante extenso y modificar los diálogos en un futuro se complicaría.

Otra opción que he pensado es tener los dialogos en un fichero y cargarlos durante la ejecución, pero no sé si tantos accesos a fichero podría relantizar el refresco de pantalla.

El texto ocupa bastante poco en memoria. Mi sentido arácnido me dice que puedes cargar todos los textos de tu juego para el idioma seleccionado cuando cargas (y los cambias al seleccionar idioma) y no va a ser un problema.

[EX3]

Como te dice FANatiko. Carga todo el archivo de diálogos en memoria y después implementa alguna función que te devuelva la cadena de texto correspondiente mediante un ID o clave que asignes. De esa forma te sera fácil meter texto en cualquier parte de tu juego sin importar el idioma.

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

TrOnTxU

Estoy de acuerdo con EX3 y con FANatiko. Carga los textos cuando selecciones el idioma, y referencia los textos desde un array, o con una clase que lo controle, por ejemplo:


class LocaleManager
{
  public:
...
    void load_language(const char *path);
    const char* get_string(unsigned int id);
...
};


Una de las formas de "automatizar" el proceso de relacionar/actualizar las cadenas y mantener los datos de texto, es crearte una herramienta que te cree un formato binario propio con los textos por una parte y un header de C++ por otra. Aunque, realmente se suelen crear un binario por idioma.

Uno de mis sistemas preferidos (que me ha funcionado desde moviles java de antaño,  pasando por ds, wii, ...) esta basado en un solo xls (pero puedes trasladarlo a xml si lo ves mas sencillo).
La primera fila del XLS contiene las cabeceras de las columnas
La primera columna un ID. Este id tiene que respetar las normas de nomenclatura de las "variables" en c++, porque lo meteremos despues en un enum en un header.
Despues puedes poner alguna columna especial. Yo por ejemplo utilizaba la segunda columna como numero maximo de caracteres, de forma que al "compilar" el XLS con la aplicacion se comprobaba que ninguna traduccion superaba ese maximo.
El resto de columnas corresponden a los idiomas.
Cada fila entonces sera (por ejemplo):
ID | [COLUMNAS ESPECIALES] | ES | EN | FR | DE | IT |...

Para "parsear" el XLS puedes utilizar cualquier cosa, yo personalmente utilizaba una modificacion en C# de un codigo que encontre en codeproject.
La idea es que la herramienta lee el XLS y genera un header (".h") parecido a esto:
// ... header guard, etc.
namespace Locale
{
enum Enumerations
{
  TITLE_ID = 0,
  NEW_GAME_ID = 1,
  CONTINUE_GAME_ID = 2,
  ...
};
}

Por otra parte, la herramienta debe generar un binario por cada idioma (por ejemplo: es.locale.bin, en.locale.bin, ...), aunque luego podrias empaquetar en un archivo más grande si utilizas lzma, zlib o lo que sea.

Para usarlo, seria remplazar (por ejemplo):

...
mainMenu.set_title( "EL JUEGAZO" );
mainMenu.add_option( "Nueva Partida", &new_game_callbak );
mainMenu.add_option( "Continuar Partida", &continue_game_callbak );
...


por


...
mainMenu.set_title( g_localeMngr.get_string( Locale::TITLE_ID ) );
mainMenu.add_option( g_localeMngr.get_string( Locale::NEW_GAME_ID), &new_game_callbak );
mainMenu.add_option( g_localeMngr.get_string( Locale::CONTINUE_GAME_ID ), &continue_game_callbak );
...


Hay estudios (y con juegazos en el mercado) que prefieren que la herramienta directamente edite el archivo "fuente", de una manera parecida a como lo harias por ejemplo con excel.

Para hacer esto es bastante facil con WindowsForms, el dataGrid, y algo de serializacion XML, y en poco tiempo puedes tener un programa de este tipo funcionando. Pero al final la parte de generar el header y los binarios es la misma.

En cuanto los binarios, solo tener en cuenta que deben estar ordenadas las cadenas, conforme el orden de las filas, para que coincidan con los indices del enum. Si utilizas ASCII o UTF-8 no tendrás problemas con el endianess. Debes tener una tabla con la direccion donde empieza cada cadena, esto lo puedes precalcular y guardar en el binario, o crear la tabla durante la carga del binario (ten en cuenta que seguramente tendras un caracter de final de cadena que puedes utilizar para avergiuar la longitud de cada cadena).

Otras opciones se podrian realizar con std::maps, o con hashtables, etc. Pero esta es relativamente sencilla y efectiva.


Me ha quedado un tostón, como siempre ^^
Espero que te sirva de algo al menos.

Un saludo.
Vicent: Linked-In  ***  ¡¡Ya tengo blog!!

Hyruleoflink

Gracias por vuestros consejos. Voy a intentar implementar la propuesta de TrOnTxU. ¡Ya os contaré si lo he conseguido!

TrOnTxU

#5
A raiz de este post he estado revisando la herramienta, porque tenia que actualizar alguna cosa.
Como sé que hacer la herramienta es un "peñazo", te he preparado una version de la mia. Y he incluido un ejemplo sencillo en C++ de como gastarla.
La herramienta es .NET no sé que version para windows. O sea que si no te funciona tendrás que ponerte el último framework.

El ejemplo está exportado como plataforma: STD_CPP_LE (Standard C++ Little Endian) y ASCII (realmente un ISO-899.. nosequé).
Si no vas a compilar para plataformas Big Endian no tienes problemas.

http://mural.uv.es/vibrun/locale_stratos.zip

Espero que te ayude. Ya me dices que te parece.

Salu2

EDIT: El Italiano no está traducido ^^, que nadie se ralle ni se enfade  0:-)

Vicent: Linked-In  ***  ¡¡Ya tengo blog!!

Hyruleoflink

Muchisimas gracias!!!

Me has ahorrado horas de teclear código y la muerte de algunas neuronas depurándolo posteriormente ^^

Todo funciona perfectamente, y el uso de la herramienta es sencillo. De verdad, muchas gracias. A ver si ahora que está solucionado el problema del idioma puedo tener terminado el proyecto en un par de semanas... ¡Ten seguro al 100% que saldrás en los créditos en la parte de agradecimientos!






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.