Página 1 de 2

[SOLUCIONADO]Varios idiomas en una aplicación

Publicado: 20 Oct 2011, 16:50
por arkcrew
Hola a todos,

Estoy retocando una de mis aplicaciones, ya saben, reorganizando el código,depurándolo lo mñás posible, ya que es una aplicación que he estado actualizando durante dos años y está super liada de funciones nombres raros etc...

En fín, mi idea es que como tendo el código en dos idiomas (inglés y español) , alguna manera de poder añadir más idiomas sin necesidad de depender de archivos externos, y que esté organizado de alguna manera que sea facil de actualzar o añadir más idiomas...

Actualmente tengo una función que me devuelve el idioma que está siendo usado en el ordenador, se pasa a un select-case y ahi una lista de variables con los textos.. , resumiendo, una chapuza, que es lenta a la hora de editar y liosa ya que hay muchas variables que se repiten...
Dado que quiero organizar el código, pues me gustaría saber si hay alguna manera más cómoda de hacerlo.

Había pensado en utilizar alguna matriz, algo en plan $espanol[X]=[x,x,x,x,x,x,x,x,x,x] algo así, pero nose, son textos, en ocasiones largos, y me lia bastante, quizás esta sea una de las mejores opciones, pero me gustaría saber vuestra opinión.

Otra cosa, supongamos que lo hago en matrices, hay algo para poder pasar a seguir escribiendo en la siguiente linea, me explico:

$espanol[X]= [x,x,x,x,x,x,x &_
& , x,x,x,x,x]

Saludos

Re: Varios idiomas en una aplicación

Publicado: 20 Oct 2011, 17:33
por BasicOs
Aquí hay una función que se llama algo así como
; Load the language file. (lee de fichero texto hacia matrices)
_LoadOSLang()

y hace algo parecido:

http://www.emesn.com/autoitforum/viewto ... f=4&t=2904

El código es un ejemplo para ver como se puede estructurar, recogiendolo de unas matrices, y estas matrices de unos archivos de texto muy fáciles de modificar.
Salu22:)

Re: Varios idiomas en una aplicación

Publicado: 20 Oct 2011, 18:52
por arkcrew
Muchas Gracias BasicOs,

En cuanto tenga un momento me la miro, y os paso como me quedó..

Saludos!

Re: Varios idiomas en una aplicación

Publicado: 20 Oct 2011, 20:53
por yasmany
KE BIEN ME SURGE UNA IDEA para empezar hacer en dos idiomas los programas ggg :smt001
ZALU2 YO INTENTARE A MI MODO

Re: Varios idiomas en una aplicación

Publicado: 21 Oct 2011, 08:42
por Ximorro
Ese tema se ha tratado varias veces por el foro, buscad que se comentaban algunas posibilidades variadas.
Pero aunque no te guste me temo que lo más cómodo será tener archivos externos, además eso facilitaría la incorporación de nuevos idiomas sin necesidad de recompilar el programa.

Re: Varios idiomas en una aplicación

Publicado: 21 Oct 2011, 12:13
por arkcrew
Mmm, si la verdad es que así es más comodo, incluso podría hacer la parte de los idiomas autoactualizable ya que el código seguiría una serie de pautas y si no encontrara el idioma que hay en la máquina, podría evr si existe en el servidor, y sino , tirar del inglés que es más universal..

Gracias por la ayuda!
Saludos!

Re: Varios idiomas en una aplicación

Publicado: 21 Oct 2011, 12:23
por Ximorro
En este comentario y siguientes exponía Jamaro el problema y comentábamos algunas posibilidades:
http://www.emesn.com/autoitforum/viewto ... 352#p10352

Está mezclado con otras cosas, igual por eso no era tan fácil de encontrar...

Re: Varios idiomas en una aplicación

Publicado: 21 Oct 2011, 12:36
por arkcrew
Gracias Ximorro por tu respuesta, pero ya he comenzado con el código, os dejo lo que llevo y mi idea final de como debe quedar...

Code:

Código: Seleccionar todo

; #FUNCTION# ====================================================================================================================
; Name ..........: _LoadOSLang
; Description ...: Load language file.
; Syntax ........: _LoadOSLang(  )
; Parameters ....:
; Return values .: Success		- Returns None
;				   Failure		- Returns None
; Author ........: João Carlos (Jscript FROM Brazil) /modificado por arkcrew
; Modified ......:
; Remarks .......:
; Related .......:
; Link ..........:
; Example .......: _LoadOSLang(  )
; ===============================================================================================================================
Func _LoadOSLang($lang)
	Select
		Case $lang = "Spanish" ; Espanol
			$VAR = IniReadSection(@ScriptDir&"\Languages.au3", "es")
		Case $lang = "English" ; Ingles
			$VAR = IniReadSection(@ScriptDir&"\Languages.au3", "en")
		Case Else
			MsgBox(4096, "Error", "No languages matches!")
	EndSelect
EndFunc   ;==>_LoadOSLang
Con esto, al pasar el valor como $VAR[1][X] obtengo el valor de esa posicion, asi tengo ya cargado el idioma

Saludos!

Re: Varios idiomas en una aplicación

Publicado: 21 Oct 2011, 13:40
por BasicOs
A eso hay que añadirle algo, manteniendolo simple.
Si lo quieres hacer con esto tendrías que hacer un stringsplit() para llenar la variable-matriz $var, y tener separados por comas cada concepto dentro del fichero INI, con una matriz del tipo $VAR=Stringsplit de IniReadSection(@ScriptDir&"\Languages.ini", "es") en Languages.ini (NO USAR .AU3 porque no es un fuente)

Sería dentro del ini, Los contenidos que llenarán $Var:
es=Mi programa, Mi texto1, Aviso de algo, Aviso de otra cosa, Mitexto3, Salir, ARchivo, Abrir, Cerrar, mas textos, y mas, etc, fin
---- $var[1], ------- $var[2], $var[3], etc..
Claro y tener por orden bien claro a que pertenece cada posición, para llamarla en cualquier momento con $var[3].

Código: Seleccionar todo

$VAR = stringSplit( IniReadSection(@ScriptDir&"\Languages.ini", "es"))
msgbox(0,"Texto primero",$var[1]) es el texto primero que está separado por comas, y así los demás
Ver en la ayuda sintaxis de StringSplit.

Salu22:)

Re: Varios idiomas en una aplicación

Publicado: 21 Oct 2011, 16:04
por arkcrew
Hola BasicOs,

En realidad la función va la la perfección, solo que debo llamarla en la primera línea del código, os dejo como lo he hecho:

Código: Seleccionar todo

Global $lang = _Language()

Select
	Case $lang = "Spanish" ; Espanol
		$idioma = IniReadSection(@ScriptDir & "\Languages.ini", "es")
	Case $lang = "English" ; Ingles
		$idioma = IniReadSection(@ScriptDir & "\Languages.ini", "en")
	Case Else
		MsgBox(4096, "Error", "No languages matches!")
EndSelect
Esto está en la parte superior del código, y a partir de ahi, ya cuando queiro obtener un valor lo saco mediante $idioma[numero caracter][1].. con eso me va perfecto, el problema lo tengo a la hora de los breaklines, tengo dentro del ini una cadena que es: "xxxxxx" & @CRLF & "xxxxxxxxx"
Como hago para que eso se vea nromal en un traytip, es decir, ahroa se ve en el tray "xxxxxx" & @CRLF & "xxxxxxxxx" , pues que se vea xxxxx (el break) y en la linea siguiente xxxx

Espero haberme explicado

Saludos!

Re: Varios idiomas en una aplicación

Publicado: 24 Oct 2011, 11:17
por Ximorro
¿Qué forma tiene el INI?
Tienes que tener cuidado al leer así las cadenas, las estás leyendo por posición, por ejemplo dices $idioma[numero caracter][1] (supongo que con "numero caracter" quieres decir "número cadena") así que $idioma[5][1] lee la quinta cadena (la posición cero se guarda para el número de elementos).
Vale, pero no es del todo seguro porque los archivos INI no funcionan por posición sino por parejas clave-valor, así que en alguna ejecución (o si cambian la implementación del gestor de archivos INI) las posiciones cambien. En principio un INI está pensado para ser accedido por secciones y claves, no por posiciones.
En los enlaces que te ponía insinuaba algo sobre diccionarios, para esto sería ideal, aunque más complicado (pero muy eficiente)

Lo de los retornos creo que se puede resolver, o poniendo caracteres especiales que proceses antes de sacar la cadena (cambiando con StringReplace esos caracteres especiales por @CRLF, por ejemplo). O quizás usando StringFormat para mostrar todas las cadenas. Por ejemplo con StringFormat la secuencia "\n" es el retorno de carro:

Código: Seleccionar todo

$cadena = "Esta es una cadena de dos líneas.\nEsta es la segunda línea"
MsgBox(0, "Mensaje", StringFormat($cadena))
Si usas esto entonces tienes que tener en cuenta las peculiaridades de StringFormat, por ejemplo hay que doblar las barras invertidas y los "tantos por ciento". Por otro lado esto te permite tener variables en las cadenas, cosa que de otra manera no sé cómo se haría fácilmente, piensa que en diferentes idiomas una misma parte de la frase pude no ir en el mismo sitio.
Por ejemplo si tenemos que poner "Contraseña de <usuario>" pero queremos poner el nombre del usuario, puedes hacer la cadena en el archivo de idioma como "Contraseña de " y al mostrarla añadir el nombre de usuario. Pero entonces por ejemplo al hacer la versión en inglés no es "algo en inglés" seguido del usuario, pues en inglés se pondría "<usuario>'s password", es decir, en inglés no tenemos que añadir el nombre de usuario al final, ¡sino al principio!
Con los formatos esto se soluciona porque se incluye en la cadena dónde va el texto a insertar:

Código: Seleccionar todo

$cadenaEsp = "La contraseña de %s es sahdfglks"
$cadenaEng = "%s's password is sahdfglks"
MsgBox(0, "Mensaje EN ESPAÑOL", StringFormat($cadenaEsp, @UserName))
MsgBox(0, "Mensaje EN INGLÉS", StringFormat($cadenaEng, @UserName))

Re: Varios idiomas en una aplicación

Publicado: 24 Oct 2011, 14:46
por chekok
Con el tema de una aplicación traducida en varios idiomas, hay un sistema más que rápido de mantener y de crear nuevas traducciones. El planteamiento es el siguiente:

Se hace una función que lee y guarda los label de cada control y Mensajes en un fichero o tabla, controlando si se repiten, para no crear duplicados.
Otra función que cuando activo la traducción, sustituye el equivalente del idioma elegido de todos los textos recopilados en dicho fichero creado anteriormente.

El objeto de este tipo de traductor, es la versatilidad a la hora de crear traducciones, ya que si la palabra "Salir" se repite en mil y una pantallas, no tendremos mil y una líneas "Salir" = "Exit","Eixir", si no que tendremos una sola línea "Salir" y la función se encarga de traducir dicho texto en todos los lugares donde aparezca en nuestra aplicación.

Espero que hayais entendido la idea. Dicho sistema es usado por ejemplo en ITACTIL TPV.

Re: Varios idiomas en una aplicación

Publicado: 24 Oct 2011, 14:54
por BasicOs
No se la diferencia de lo que dices, con la que usa Jscript en Oslang del programa de control remoto, aquí: http://www.emesn.com/autoitforum/viewto ... f=4&t=2904

Al final también igualmente es una matríz y el programa coge de la matriz el valor que se use para la salida de texto en cada momento del programa.
Si tienes algo de código o bien mostrar un poco como se traspasa el valor traducido a la función que la usa (ejemplo como mensaje msgbox()).

Salu22:)

Re: Varios idiomas en una aplicación

Publicado: 24 Oct 2011, 16:27
por arkcrew
Hola,

En primer lugar gracias a todos por la ayuda, me ha servido de mucho..
Al final se solucionó como dijo Ximorro, con los \n y los StringFormat, el ini en un principio solo lo tengo en español e inglés pero que es cuestión de poner más idiomas, pero debo mirar ciertas estructuras, ya que no siempre me coinciden lso datos que debe mostrar, como me ha pasado con el alemán.. pero el caso es que está solucionado y funciona a la perfección, dejo un minicódigo con como lo tengo yo para futuras referencias de los usuarios ;)

Code:

Código: Seleccionar todo

Global $lang = _Language()
Select
	Case $lang = "Spanish" ; Espanol
		$idioma = IniReadSection(@ScriptDir & "\Languages.ini", "es")
	Case $lang = "English" ; Ingles
		$idioma = IniReadSection(@ScriptDir & "\Languages.ini", "en")
	Case Else
		MsgBox(4096, "Error", "No languages matches!")
EndSelect
Func _Language()
	Select
		Case StringInStr("0409 0809 0c09 1009 1409 1809 1c09 2009 2409 2809 2c09 3009 3409", @OSLang)
			Return "English"
		Case StringInStr("040a 080a 0c0a 100a 140a 180a 1c0a 200a 240a 280a 2c0a 300a 340a 380a 3c0a 400a 440a 480a 4c0a 500a", @OSLang)
			Return "Spanish"
		Case Else
			Return "Otro"
	EndSelect
EndFunc   ;==>_Language
Y la estructura del ini es la siguiente:

Código: Seleccionar todo

[es]
1=cadena 1\nlinea 2
2=cadena 2
[en]
1=chain 1\nline 2
2=chain2
Espero os resulte útil...

Saludos!

Re: [RESUELTO]Varios idiomas en una aplicación

Publicado: 25 Oct 2011, 08:04
por Ximorro
Sí, pero os advierto que con los INI si por ejemplo se cambian de posición los textos, faltan o sobran, se descuadra todo. De hecho estás diciendo que no siempre saca el texto que toca.

Si quieres sacar la cadena que has marcado como "1", tienes que buscar la clave "1" a ver en qué posición de la matriz de IniReadSection, porque no necesariamente está en la posición 1.
Una vez sabes la posición usas ese índice para tomar el valor de la cadena.

O eso o tienes que asegurarte de que el INI es leído secuencialmente.

He hecho una versión con diccionarios que hace esto de buscar la clave de forma ultra-eficiente, os lo pongo en otro post porque he hecho un programita completo (eso sí, totalmente chorra, con unas pocas cadenas) para mostrarlo.

Re: [RESUELTO]Varios idiomas en una aplicación

Publicado: 26 Oct 2011, 13:08
por Ximorro
Lo dais por resuelto pero no mostráis un programa que lo use.
Porfa poned un ejemplo con un formulario multilenguaje para que los usuarios vean cómo se hace.

Por mi parte he hecho una versión que usa diccionarios, aquí la tenéis:
http://www.emesn.com/autoitforum/viewto ... 138#p12138

Re: [SOLUCIONADO]Varios idiomas en una aplicación

Publicado: 06 Nov 2011, 21:24
por jamaro
Hola tod@s:

Retomando este tema sobre los idiomas, releyendo otros hilos y retocando un poco algo que empecé y no terminé, hoy puedo adjuntar unas pruebas "a mi manera" con lo comentado ya en este foro.

El uso de idioma lo hago con archivos de texto, con el formato clave=texto asignado a la clave.
Utilizo dos archivos de idioma, el "idioma usado" y el "idioma por defecto" (en este caso español) por si falla alguna entrada en el "idioma usado".
He creado una función llamada _bpi (que sería Buscar Palabra Idioma) en la que se busca la clave en la matriz para devolver el texto asignado a esa clave, pero, en caso de que no exista la clave buscada en el "idioma usado", devolverá el texto de la clave del "idioma por defecto" en el que sí debe existir todas las claves.

Espero aportar un granito de arena a las ideas que ya se han comentado por aquí.

Un saludo.

EDITO: Acabo de probar a añadir un pequeño GUI, tal y como hizo Ximorro, y ¡funciona muy bien! Lo que sí que veo (en mi código) es que es necesario que el archivo de texto del idioma no puede tener líneas en blanco intermedias, aunque se puede utilizar algo como "-=--------------------------------" o simplemente "=", para separar las distintas secciones del archivo de idioma.

Código: Seleccionar todo

#include <GUIConstantsEx.au3>
#include <TabConstants.au3>
#include <WindowsConstants.au3>
#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate(_bpi("Form1"), 623, 449, 192, 114)
$Tab1 = GUICtrlCreateTab(40, 30, 541, 381)
$TabSheet1 = GUICtrlCreateTabItem(_bpi("TabSheet1"))
$TabSheet2 = GUICtrlCreateTabItem(_bpi("TabSheet2"))
$TabSheet3 = GUICtrlCreateTabItem(_bpi("TabSheet3"))
$TabSheet4 = GUICtrlCreateTabItem(_bpi("TabSheet4"))
GUICtrlCreateTabItem("")
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit

	EndSwitch
WEnd
Y añadiendo en el documento de idioma las líneas...

Código: Seleccionar todo

Form1=Formulario con pestañas
TabSheet1=Archivo
TabSheet2=Edición
TabSheet3=Formato
TabSheet4=Ver
...ya está.

Si en el idioma usado (inglés) no está todo (por ejemplo, aquí falta las claves TabSheet2 y TabSheet3) ...

Código: Seleccionar todo

Form1=Form with Tabs
TabSheet1=File
TabSheet4=View
... usará los textos en español (por defecto) que no encuentre en el de inglés.

Además, no hace falta ni molestarse en cambiar los nombres de los controles que se crean con el diseñador de formularios KODA y se puede aprovechar el mismo nombre para ponerlo como "clave" en el archivo de idioma.

Gracias al foro, otra cosita más para añadir a nuestros programas.

Re: [SOLUCIONADO]Varios idiomas en una aplicación

Publicado: 07 Nov 2011, 01:47
por BasicOs
Hola felicidades por el código, y por lo de la idea por defecto, porque muchas veces puede faltar una clave y causar un error como el de oslang de jsscript.
Yo en vez de usar nombres crípticos para la variable, usaría normbres más descriptivos en español o en inglés:
en vez de :
$TabSheet1 = GUICtrlCreateTabItem(_bpi("TabSheet1"))

pues :

$TabSheet1 = GUICtrlCreateTabItem(_bpi("NombreUsuario"))

Con lo que en el archivo de texto sería;
NombreUsuario=Juan Lopez
en vez de
TabSheet1=

Con lo que aumenta la facilidad en la lectura del código y disminuye la necesidad de comentar e informar cuando se vuelve a releer el código al paso del tiempo :smt023 :smt023 :smt023
Salu22:)

Re: [SOLUCIONADO]Varios idiomas en una aplicación

Publicado: 07 Nov 2011, 10:56
por Ximorro
Buen trabajo jamaro.
Cuando tengáis programas de muchas cadenas os recomiendo encarecidamente que miréis mi ejemplo de los diccionarios. No es porque lo haya hecho yo, yo sólo he hecho el ejemplo, no el objeto diccionario, que es lo que realiza la magia.
Pensad que en este caso cada vez que buscas una cadena hay que ir buscando por la matriz. Tu función de búsqueda tiene 12 líneas de código, y _ArraySearch 64 líneas. Con diccionarios todo eso se hace en UNA línea, que encima se ejecuta megarápido porque está accediendo a una tabla hash.

Yo no implementé lo del lenguaje por defecto pero indiqué cómo hacerlo, y es superfácil. Simplemente se carga el idioma por defecto, y después se machaca lo leído con el seleccionado. Las cadenas que falten en el segundo lenguaje saldrán en el que esté por defecto sin hacer nada en la función de búsqueda (que no es una función, es una simple petición al diccionario para que te dé la cadena correspondiente a esa clave).

Por cierto, podrías hacer algo parecido, usando sólo una matriz de idioma, cargas directamente en $aRecordsU el idioma por defecto y después el traducido (esta segunda vez buscando por clave, claro, no por posición). Las cadenas que no estén en el traducido no se tocarán y si se usan saldrán en el idioma por defecto. Eso hará más lento el setup pero más rápida la búsqueda en la matriz, pues para una cadena no encontrada se busca en TODA la matriz de usuario, y de media en la mitad de la del idioma por defecto. Usando sólo una matriz la media de búsqueda siempre es la mitad de la matriz. Es decir, pasamos de leer 1'5 matrices a leer 0'5.


Ojo que la implementación de jamaro está realmente bien, no me malinterpretéis. No es su ejemplo el problema, sino el uso de matrices, que son lentas al hacer la búsqueda lineal.
Con matrices se podría acelerar algo ordenando las claves y haciendo una búsqueda binaria, AutoIt lo tiene implementado con _ArrayBinarySearch, desgraciadamente esa función sólo sirve para matrices de una dimensión, así que o hay que modificarla o se usan dos matrices separadas, una para las claves (donde buscamos el índice con la búsqueda binaria) y otra con las cadenas (donde tomamos el texto con el índice encontrado anteriormente).
Pero para meterse en ese trabajo (que para practicar programación me parece realmente interesante) sigo prefiriendo la tabla hash, seguirá siendo mucho más rápido.

Re: [SOLUCIONADO]Varios idiomas en una aplicación

Publicado: 08 Nov 2011, 00:37
por jamaro
Gracias BasicOS y Ximorro por vuestros comentarios.

Ximorro, como siempre, analizando el rendimiento del código. La verdad es que no utilicé los diccionarios, pensando que podría darse el problema de que un usuario no tuviera en su ordenador el Objeto necesario, pero ya he leído tu respuesta en otro hilo donde comentas que lo raro sería que no estuviera.

Como habrás visto, básicamente es una adaptación a matrices de tu programa con Diccionarios. Quizás opte por los Diccionarios, o quizás siga con el método rudimentario de las matrices, dado que los programas que yo pueda hacer no serán muy grandes (al menos respecto a los textos, etiquetas y demás que usen los idiomas) y la velocidad en el proceso puede que no sea realmente importante.

Gracias por vuestra sabiduría :smt038