martes, 25 de noviembre de 2008

Multi Idioma con [x]Harbour + FiveWin

   En esta ocasión vamos a implementar un sistema multi idoma, basado en DLL de recursos. Esto os podrá servir para distribuir vuestras aplicaciones en diferentes países, o en un mismo país con diferentes idiomas. En Baleares al igual que en otras comunidades autonomas de España, existen dos idiomas cooficiales, Castellano y Catalán. Es habitual, y sobre todo en organismos públicos que soliciten las aplicaciones en multi-idioma, o directamente traducidas al Catalán.

Para solventar este problema, sin que tengamos que modificar los fuentes de nuestra aplicación, ni debamos mantener varias versiones en paralelo, lo que haremos sera mantener tantas DLL de recursos como idiomas queramos disponer en nuestra aplicación. 

Para ello contaremos con una DLL de recursos vaciá ( vacio.dll ), que usaremos como base,  e iremos introduciendo los diálogos, y crearemos un "string table" con los mensajes que utilicemos en nuestra aplicación. (Para editar las DLL usaremos un editor de recurso cualquiera, en nuestro caso el que viene integrado con PellesC)
editor de recursos


La tabla de cadenas tiene un formato parecido al siguiente, un código y su mensaje asociado. Desde nuestro programa iremos recuperando las cadenas de texto por su numero de código.
String Table

La idea es al principio de la aplicación cargar la DLL que queramos según el idioma seleccionado, y automáticamente tendremos los diálogos y cadenas de texto en el idioma deseado.
La carga de la DLL deseada la hacemos mediante la función SetResources( via de acceso + nombre de fichero.dll), el nombre y la via de acceso puede estar guardada por ejemplo en el registro de windows, un fichero ini, o directamente solicitar la elección del idioma por parte del usuario.

En su día tuve la idea de usar Shell.Applucattion y las extensión de NTF, para grabar junto a la DLL la descripción del idioma, pero resulto ser un fiasco, debido a que solo funciona con NTF, y en instalaciones con FAT32 no funciona, y ademas al comprimir o hacer paquetes de instalación, se pierde la información adicional de los ficheros, a modo de curiosidad, y para el que quier ver los fuentes y el manejo de Shell.Application, aquí os dejo los fuentes.

Recapitulando, al iniciar el programa, cargamos la DLL de recusos deseada
Ejemplo:
oAppl:cLng:=GetLng() //Funcion que recupera el idioma
SetResources(oAppl:cDirLocal+"Resource\ppcinst"+oAppl:cLng+".dll")
oAppl:hDll:=GetResources()
Los diálogos, ya los tenemos traducidos directamente en el diseño del recurso.
Para recuperar las cadenas de texto, usaremos la función LoadString(hDll, nResid ), le debemos pasar dos parametros, el primero es el handler del modulo que contiene las cadenas de texto, y el segundo el codigo de la cadena que quermos cargar.
LoadString( oAppl:hDll, 10001 )

Para hacerlo más fácil de leer y manejar, os recomiendo crear un fichero CH para incluir en vuestro programa, a modo de diccionario, donde iremos definiendo un texto mas legible asociado a la función y código de cadena a recuperar.

include


De esta forma por ejemplo visualizar un mensaje avisando de que la aplicación ya esta en ejecución pasaría de un críptico

MsgStop( LoadString( oAppl:hDll, 10001 ) )
a
MsgStop(TXT_EXERUNNING)

bastante mas descriptivo.

Aquí os pongo un pequeño ejemplo para ver el funcionamiento de lo descrito anteriormente.
prgmultilng

MultiLng.prg
MultiLng.zip