Por Francisco San Pablo idioma.zip
¿Cómo hacer una aplicación Multiidioma?
La respuesta es aparentemente sencilla, en vez de usar los caption de los
objetos, con cadenas monoidiomáticas, puedes hacer que guarden un valor numérico y apunten a una tabla
con las cadenas especificadas para los diversos idiomas.
El
planteamiento es correcto pero ver ‘en diseño’ esas pantallas sería bastante depresivo pues serían una
colección de números sin aparente sentido. Además al estar diseñando tendrías
que estar constantemente guardando en la tabla de cadenas las diversas cadenas
y sus equivalencias. Te exigiría una disciplina verdaderamente germánica.
Una
alternativa, que es la que aquí propongo es crearnos una tabla con los name de
los objetos e invocarla en el INIT de los formulario y si se encuentra la
cadena especificada para el idioma deseado entonces se da el ‘cambiazo’. Si no
se encuentra se mantiene la cadena que se ha puesto en el diseñador.
Es
un sistema bastante cómodo pues la aplicación que ya tienes acabada y
funcionando le puedes poner en el .INIT del Form la llamada al método que luego
te voy a escribir y tu aplicación ‘monolingüe’ pasa a ser una aplicación
multilingue sin odiosos y costosos cambios. Además permite que tu aplicación
siga entregándose y funcionando mientras acabas la traducción de todos los
textos pues cuando no existe un texto alternativo para el idioma deseado te
toma el de por defecto.
Bien,
pues aquí está el código que como no es demasiado extenso te lo pongo todo.
Primero,
te trascribo el método o función que se da una vuelta por todos los objetos del
formulario viendo si el name coincide con el name guardado en la tabla de
idiomas SYSIDIOM. Si se encuentra y estamos en el idioma especificado entonces
se procede a cambiar el caption del objeto.
*----
CAMBIAIDIOMA ---- *
*
LPARAMETERS
loObjTratar, lcNombreObj
LOCAL
lnNumObj, lnCont, lcExpBusqueda, lcAuxExp, lcAuxClase, ;
lnCont2, lnNumAux
IF NOT USED("SYSIDIOM")
SELECT 0
USE SYSIDIOM
SET ORDER TO TAG CLAVE
ELSE
SELECT SYSIDIOM
ENDIF
*-
Clase a la que pertenece el objeto de objeto
lcAuxClase =
UPPER(loObjTratar.baseClass)
*-
Expresión de búsqueda general, se cambia luego si es necesario
lcExpBus =
PADR( ALLTRIM(lcNombreObj) + "." + ;
loObjTratar.name, 50 ) +
gcIdioma
lcExpBusqueda
= PADR( ALLTRIM(SYS(1272,loobjtratar)), 50 ) + gcIdioma
DO CASE
CASE lcAuxClase =
"FORM"
*- Expresión de
búsqueda general, se cambia luego si es necesario
lcExpBusqueda = PADR( "screen."
+ loObjTratar.name, 50 ) + gcIdioma
*- Cambia el título si es un form
IF SEEK(
lcExpBusqueda, "SYSIDIOM")
lcAuxExp = ALLTRIM(
SYSIDIOM.descrip )
loObjTratar.caption =
lcAuxExp
ENDIF
lnNumObj =
loObjTratar.ControlCount
FOR lnCont = 1 TO lnNumObj
THIS.mcambiaidioma(loObjTratar.Controls(lnCont), loObjTratar.name)
ENDFOR
CASE lcAuxClase =
"CONTAINER"
lnNumObj =
loObjTratar.ControlCount
FOR lnCont = 1 TO lnNumObj
THIS.mcambiaidioma(loObjTratar.Controls(lnCont), loObjTratar.name)
ENDFOR
CASE lcAuxClase =
"OPTIONGROUP" OR lcAuxClase = "COMMANDGROUP"
*- Número de botones
lnNumAux = loObjTratar.ButtonCount
FOR lnCont2 = 1 TO
lnNumAux
lcExpBusqueda = PADR(ALLTRIM(lcNombreObj)
+ "." + ;
loObjTratar.name + "." + ;
loObjTratar.Buttons(lnCont2).name, 50) + ;
gcIdioma
IF SEEK( lcExpBusqueda,
"SYSIDIOM")
lcAuxExp = ALLTRIM(
SYSIDIOM.descrip )
loObjTratar.Buttons(lnCont2).caption = lcAuxExp
ENDIF
ENDFOR
CASE lcAuxClase =
"PAGEFRAME"
*- Número de
pestañas
lnNumAux = loObjTratar.pageCount
FOR lnCont2 = 1 TO
lnNumAux
lcExpBusqueda =
PADR(ALLTRIM(lcNombreObj) + "." + ;
loObjTratar.name + "." + ;
loObjTratar.pages(lnCont2).name, 50) + ;
gcIdioma
IF SEEK( lcExpBusqueda,
"SYSIDIOM")
lcAuxExp = ALLTRIM(
SYSIDIOM.descrip )
loObjTratar.pages(lnCont2).caption = lcAuxExp
ENDIF
ENDFOR
CASE lcAuxClase =
"GRID"
lnCont2 = 1
DO WHILE .T.
*- Continua mientras
hay columnas que tratar
IF TYPE('loObjTratar.columns(lnCont2)')
<> "O"
EXIT
ENDIF
*- Procesa los controles que hay dentro
de una columna
xx =
loObjTratar.columns(lnCont2).ControlCount
FOR lnx = 1 TO xx
THIS.mcambiaidioma(loObjTratar.columns(lnCont2), lcNombreObj)
ENDFOR
lnCont2 = lnCont2 + 1
ENDDO
CASE lcAuxClase = "COLUMN"
lnCont2 = 1
DO WHILE .T.
*- Continua mientras
hay controles que tratar
IF TYPE('loObjTratar.controls(lnCont2)')
<> "O"
EXIT
ENDIF
THIS.mcambiaidioma(loObjTratar.controls(lnCont2), lcNombreObj)
lnCont2 = lnCont2 + 1
ENDDO
CASE lcAuxClase =
"LABEL" OR ;
lcAuxClase =
"COMMANDBUTTON" OR ;
lcAuxClase =
"CHECKBOX" OR ;
lcAuxClase =
"HEADER"
IF SEEK( lcExpBusqueda,
"SYSIDIOM")
lcAuxExp = ALLTRIM(
SYSIDIOM.descrip )
loObjTratar.caption =
lcAuxExp
ENDIF
ENDCASE
El
código anterior, debe ser invocado desde el INIT del formulario. Al llegar a
ese método ya existen todos los objetos pero todavía no se visualizan y es el
momento conveniente para cambiarlos. Si tienes una clase que gobierna todos los
formularios es el sitio oportuno para ponerla. Si no la tienes deberías usar un
código parecdio al que ahora te pongo para invocar la función o método que
realiza un inventario de todos los objetos del formulario y realiza los cambios
oportunos:
*
* CAMBIAMOS IDIOMA
*
*- Expresión de búsqueda
lcExpBusqueda = PADR(THISFORM.name, 50 ) + gcIdioma
IF NOT USED("SYSIDIOM")
SELECT 0
USE
SYSIDIOM
SET
ORDER TO TAG CLAVE
ELSE
SELECT SYSIDIOM
ENDIF
*- Cambia el título principal de la ventana
IF SEEK( lcExpBusqueda, "SYSIDIOM")
lcAuxExp = ALLTRIM( SYSIDIOM.descrip )
THISFORM.caption = lcAuxExp
ENDIF
lnNumObj = THISFORM.ControlCount
FOR lnCont = 1 TO lnNumObj
oAPP.mcambiaidioma(THISFORM.Controls(lnCont), THISFORM.name)
ENDFOR
Unicamente
reseñar que los campos de la tabla SYSIDIOMA son:
OBJETO
C(30), Idioma C(3), Descrip C(30)
Rellenada
de la siguiente forma
FrmMain.lblFile.Caption CAS Archivo
FrmMain.lblFile.Caption ENG File
FrmMain.Caption ENG Help
FrmMain.lblFile.Caption SPA Ayuda
FoxPress – Abril de 2006
© 2006 FoxPress. All rights reserved