Una Aplicación con Independencia de Idioma
Por Robert Bravery
Traducción : Juan Manuel Espinosa G.

Introducción

En mi país, Africa del Sur, hay once idiomas oficiales. Eso es correcto once. Eso significa que ciertas publicaciones se publican en estos once idiomas oficiales. Puedes imaginar intentar escribir una aplicacion para satisfacer tantas variaciones. Lo que no querrías hacer es tener un formulario diferente, menu, informe o reporte para cada idioma. No se tu pero eso es un trabajo mayusculo, sin contar la pesadilla de manejar los cambios a estos objetos. ¿Asi que, que podemos hacer? Bien, la situación ideal es tener un objeto (formulario, menú o informe) y tener la traducción hecha directamente o inmediatamente y transparentemente. Hay muchas maneras diferentes de lograr esto. Algunas son muy extensas y laboriosas y algunas son difíciles de controlar. Podriamos, por ejemplo, tener una tabla con las filas y columnas que representan los elementos del objeto y las traducciones del idioma. Pero entonces podrías tener una tabla separada para cada objeto. Esto puede hacerse pero es más bien lento porque pudieras terminar en una situación dónde tienes que mover continuamente el puntero de registro localizando o buscando la fila correcta o por otra parte moverse al registro correcto para la traducción. O, podrías usar variables de memoria. Vaya que podría ser una pesadilla.

Entra a las *.DLL, tambien conocidas como bibliotecas dinamicas de enlace. ¡Y eso es exactamente lo que son!. Es un archivo que contiene una biblioteca de recursos. Estos recursos puede ser cualquier recurso de Windows, desde mapas de bits (bitmaps) a cursores, a cadenas de datos o texto. Posiblemente estás usando ya una de estas DLL en el formulario de resource.dll, cuando seleccionas un bitmap para un boton. Así, la idea es entonces tener una biblioteca de recursos que un formulario pueda acceder y pueda usar independientemente. La mejor manera, en mi opinión, es crear un DLL para cada idioma que piensas usar con las cadenas del texto diferentes representadas por recursos diferentes en la DLL. Cada ID de recurso será exactamente el mismo por todos los idiomas. Por ejemplo, he puesto juntos en un formulario sencillo los idiomas inglés y afrikaans. Por consiguiente, si un recurso con un ID de 15 tuviera un valor de “ABC” en el english.dll, entonces el mismo ID de recurso en el afrikaans.dll representará el equivalente del afrikaans, que dice “abc.”

El único el problema es que no puedes crear un recurso DLL en Visual dBASE. Necesitarías una herramienta de terceros u otro lenguaje de desarrollo que pueda crear, compilar y enlazar o editar una DLL. Yo uso Visual C++ para hacer esto. Pero si no tienes tal animal podrías tener el “Resource Workshop” (RW) proporcionado con Visual dBASE 5. Con esto puedes editar muchas DLL de menor tamaño para satisfacer tus necesidades. Encontré que el RW tiene una limitación de tamaño. La otra limitación que el RW tiene es ser principalmente un editor de 16 bits por lo que no puedes esperar crear una DLL para un sistema de 32 bits como las desarrolladas para Visual dBASE 7.x. Pero lo que puedes hacer es editar una DLL existente de 32 bits y guardarla y el RW la guardará intacta. Aquí tienes dos opciones: 1) encontrar una DLL de 32 bits, copiarla a un nuevo nombre en tu directorio de trabajo. Luego editarla, anular todos los recursos originales y agregar los propios o, 2) usar la DLL vacia proporcionada en el dUFLP, disponible en los grupos de noticias (newsgroup) y diferentes sitios Web alrededor del mundo.

Dicho esto, crearemos un formulario sencillo que pueda ser usado por dos idiomas diferentes, Inglés y afrikaans. Me concentraré en el uso del RW porque creo que la mayoría de las personas que leen este artículo acceso a ese programa.

El Formulario

La primera cosa a realizar es crear un formulario sencillo. Crea el formulario y coloca algunos objetos en él, como texts, entryfields, pushbuttons, radiobuttons, checkboxes etc. Para el propósito de este demo mi formulario luce así:

Lo que tenemos que hacer ahora es cambiar el valor del texto de cada objeto. Normalmente hariamos esto cambiándolo vía las propiedades del objeto. Lo que haría quizás es trazar cada objeto que define lo que el objeto es y el texto deseado en tu idioma natural para que tengas un punto de referencia. Por ejemplo “Text1=Name” y “text2=Surname.”

La DLL

Si no tienes una DLL vacia de 32 bits para Visual dBASE 7.x, siempre podrías crear una. La idea es encontrar una DLL pequeña, la copias a otro nombre y a continuación la editas en el RW. Si vas a tu carpeta mugs bajo la carpeta de samples, encontrarás el archivo de mugsR.dll. Copialo a tu directorio de trabajo y cambia  el nombre a english.dll. Abre el Resource Workshop y navega a tu directorio de trabajo y abre english.dll. Para hacer esto selecciona “File…|Open Project”. Selecciona el tipo de archivo correcto usando el menu de lista. Aquí verás diferentes tipos de proyectos de recursos con los que puedes trabajar. Navega abajo hasta la linea que dice “DLL, VBX, CPL library”y seleccionala. Navega a tu directorio de trabajo bajo el listado de directorios, selecciona tu archivo, english.dll y ábrelo. Debes obtener una ventana con los diferentes recursos disponible en esta DLL en particular.

Sombrea cada uno de los recursos y eliminalos. Recuerda que estás haciendo esto con tu english.dll. Ahora con la DLL vacia (ya podrías haber usado una propia DLL vacia o una que obtuviste del dUFLP) necesitamos crear un recurso eso puede contener cadenas del texto para el valor del texto de nuestros objetos del formulario. En el RW bajo “Resource”, selecciona “New” y, a continuación, Navega a STRINGTABLE y selecciona OK.

Tendrás presente una ventana dónde puedes escribir la cadena deseada. La tabla de cadenas tiene una ID de origen, Valor de ID y columnas de la cadena. No te preocupes por las primero dos, usa los predeterminados. Es la columna de cadena que nos gustaría editar. Resalta la celda del cadena y editalo para leer “English Form.”

Para agregar un nuevo elemento de recurso, selecciona desde el menú “Stringtable” y después “New Item”. Edita la cadena con el texto deseado. Continúa haciendo esto hasta que has llegado a 17 o el número deseado de cadenas de texto para coincidir con tu formulario, menú o informe.

De nuestro formulario de demostración he usado los siguiente cadenas e IDs correspondientes. El ID es importantes ya que esto sirve como nuestra referencia a la cadena.
 
 
 1, "English Form"
 2, "Click Me"
 3, "Close"
 4, "Name"
 5, "Surname"
 6, "Choice 1"
 7, "Choice 2"
 8, "Blue"
 9, "Red"
10, "Red"
11, "Yellow"
12, "Green"
13, "Circle"
14, "Square"
15, "This is not an error. I bet you pushed the pushbutton"
16, "Alert!"
17, "OK"
   

Guarda el proyecto. Ahora copia el archivo english.dll y cambiale el nombre para denominar lo que representaría tu otra traducción. Para este demo lo he renombrado a afrikaans.dll. Una vez hecho esto abre la DLL en el RW. Observa que el archivo se representa por el nombre corto de DOS, es decir formato 8.3, por lo que el archivo será afrika~1.dll. Tu proyecto ahora tiene adentro todas las cadenas de tu versión inglesa. Esto es por qué trazados nuestro formulario para que cuando ingresamos las cadenas y editemos la cadena traducida que podamos apuntar al lado los objetos trazados el ID del recurso correspondiente para usar más tarde en el formulario. Ahora edita las cadenas con tu traducción deseada. Porque tengo que usar afrikaans, aquí esta mi traducción del afrikaans.

 
 1, "Afrikaans Vorm"
 2, "Druk My"
 3, "Sluit"
 4, "Voor Naam"
 5, "Van"
 6, "Keuse #1"
 7, "Keuse #2"
 8, "Blou"
 9, "Rooi"
10, "Rooi"
11, "Geel"
12, "Groen"
13, "sirkel"
14, "Vierkant"
15, "Hierdie is nie 'n fout nie. Ek wet dat jy die knoppie gedruk"
16, "Alarmsein!"
17, "Alles Reg"
   

Nota que cada ID correspondiente tiene una traducción. Guarda el proyecto.

El Traducción

Ahora para que nuestra forma trabaje correctamente ahora tenemos que enlazar los valores del texto del los objetos al recurso correspondiente en la DLL correcta. La sintaxis sería entonces:

 
Object.text = resource (resource_id,resource_file_name) // El id del recurso es un valor numérico y el nombre del archivo es un cadena.
   

Así, si quisiéramos el form.text1.text para que tenga el valor del afrikaans reemplazaríamos el “text1” de valor de texto con text = resource (4, "afrikaans.dll"). Esto reemplazará entonces el valor del texto con el valor del cadena correspondiente para ese id de recurso, “Voor Naam.”

Pero porque queremos que esto sea dinámico, es decir queremos que el usuario pueda escoger su idioma al tiempo de ejecución necesitamos sustituir el nombre de archivo de recurso con una ubicacion del lugar o variable. Yo utilizo _app.langdll que mantiene el nombre del archivo correcto del formulario de configuración. Entonces para hacer las cosas un poquito más fácil de leer podemos definir una lista de posiciones para la cadena numérica qué definimos al inicio del formulario:
 
 
#define form_header 1
#define form_title 1
#define form_pushbutton1 2
#define form_pushbutton2 3
#define form_text2 4
#define form_text3 5
#define form_rectangle1 6
#define form_rectangle2 7
#define form_radiobutton1 8
#define form_radiobutton2 9
#define form_checkbox1 10
#define form_checkbox2 11
#define form_checkbox3 12

** END HEADER -- do not remove this line
//
// Generated on 10/17/1999
// .......................

   

Ahora abrimos nuestro formulario en el editor de recursos e insertamos los enunciados de derechos al inicio. También necesitamos reemplazar cada valor del texto con el valor del recurso correcto. De esta manera: 

 
class langForm of FORM
with (this)
  scaleFontBold = false
  height = 16.5
  left = 16.5714
  top = 0
  width = 76.4286
  text = resource (form_header,_app.langdll)
endwith

this.TEXT1 = new TEXT(this)
with (this.TEXT1)
  height = 1.9091
  left = 3.8571
  top = 0.5455
  width = 66.5714
  colorNormal = "0x4000/BtnFace"
  alignVertical = 1 // Middle
  alignHorizontal = 1 // Center
  fontSize = 25
  fontBold = true
  text = resource (form_title,_app.langdll)
endwith

   

Y así sucesivamente hasta que todos se hayan reemplazado.

NOTA IMPORTANTE: Ten en mente que si vas a editar este formulario desde dentro el diseñador de formularios, el diseñador del formularios recuperará el valor de la cadena del archivo de recursos de modo que en lugar de text = resource (form_title, _app.langdll), tendrás text = "Tu cadena". Para superar esto, qué podría parecer al principio como un poco más de trabajo, necesitarías poner todas los remplazos del texto en algo como el evento onOpen del formulario. Pero te dejo eso a ti para experimentar para ver que satisface tus necesidades.

El Formulario de Inicio.

Para hacerlo más fácil para el usuario podemos crear un formulario de arranque que tiene, quizá, radiobuttons representando los diferentes idiomas disponibles. El usuario elige el idioma deseado y entonces activas tu aplicación. Todo se representa en su propio idioma. Al mismo tiempo un usuario diferente podría acceder tu aplicación queriendo ser presentada en su propio idioma.

Nota: Todos los datos permanecerán como fueron ingresados. Así, si se escribiera en inglés permanecerá en inglés. Sólo el texto para los objetos se cambiará.

En el evento onClick de un botón de ejecución podemos evaluar los radiobuttons y poner el resultado en una variable para nuestra aplicación p.e.
 
 
Function PUSHBUTTON1_onClick
  do case
    case form.radiobutton1.value = true
       _app.langdll="english.dll"
    case form.radiobutton2.value = true
       _app.langdll="afrikaans.dll"
  endcase
  do langeng.wfm
  form.close()
  return
   

Así si el usuario escogiera la versión en inglés el formulario luciria como esto:

Y si el usuario escogiera la versión afrikaans su formulario luciria como esto:

Conclusión

Voilà no es tan malo. Bien es rapido y hay tantas posibilidades que apenas puedo pensar en los usos. Oh, haz clic en el primer pushbutton en ambas versiones para tener una sorpresa. Estudia el código para ver cómo se cumple. Es muy sencillo. NOTA: Haz claro que es necesario ejecutar el archivo .EXE auto-extraible y abrir el archivo .WFM en Visual dBASE 7.x. Además, es necesario correr el archivo Setup.wfm.

No pienses que ésta es la única manera, o la mejor manera de hacerlo, pero me funciona, luce profesional y agrada a los usuarios. Y sé que puede parecer ser al principio un gran trabajo; pero si es planeado correctamente puede salvar mucho tiempo y frustración.

Disfrutalo.

Robert Bravery.

Para descargar la aplicación de ejemplo haz clic aquí
(es un archivo empacado de 37Kb)

Traducción por : Juan Manuel Espinosa, Desarrollador de Software en México, D.F.
Administrador de la Comunidad de dBASE en Español
puede contactarlo por e-mail en: juan_espinosa_mx@yahoo.com ó juan_espinosa@pwsmexico.com.