[SRC] Cargar Idioma desde BD "SharpDevelop 2.2 & SQLite"

Iniciado por Maurice_Lupin, 5 Mayo 2012, 23:52 PM

0 Miembros y 1 Visitante están viendo este tema.

Maurice_Lupin

Me base en un ejemplo de vb6 que encontre con google:
http://www.recursosvisualbasic.com.ar/htm/trucos-codigofuente-visual-basic/227-aplicacion-multilenguaje-con-ado.htm

Adapte el codigo a vb.net con el framework 2.0 y SQLite

Herramientas:

-   Sharpdevelop 2.2 para el .NET Framework 2.0
-   SQLite-1.0.66.0 (driver Ado.net 2.0)

Links:

http://www.icsharpcode.net/OpenSource/SD/Download/

SQLite-1.0.66.0-setup (descarguen el Setup)
http://sourceforge.net/projects/sqlite-dotnet2/files/SQLite%20for%20ADO.NET%202.0/1.0.66.0/

Una vez instalado sólo hay que Referenciar la DLL "System.Data.SQLite.dll" al proyecto.



Al final dejo el link del proyecto.
Código (vbnet) [Seleccionar]

   ' Metodo para cambiar la propiedad "Text"
   ' a todos los controles del Form
   Public Sub changeCaptions( Lista As Object)
Dim myControl As Object

If (TypeOf(Lista) Is Form) Then
setCaption( CType(lista, Form) )
End If

If Not( (TypeOf(Lista) Is ToolStripButton) Or _
   (TypeOf(Lista) Is ToolStripMenuItem) ) Then
' Labels, Buttons, Textboxs
For Each myControl In Lista.Controls
setCaption( myControl )
changeCaptions( myControl)
Next
End If

If (TypeOf(Lista) Is ToolStrip) Or _
  (TypeOf(Lista) Is MenuStrip) Then
For Each myControl In Lista.Items
If (TypeOf(myControl) Is ToolStripButton) Or _
  (TypeOf(myControl) Is ToolStripMenuItem) Then
setCaption( myControl )
changeCaptions(myControl)
End If
Next
End If

If (TypeOf(Lista) Is ToolStripMenuItem)
For Each myControl In Lista.DropDownItems
If (TypeOf(myControl) Is ToolStripMenuItem) Then
setCaption( CType(myControl, ToolStripMenuItem) )
changeCaptions(myControl)
End If
Next
End If
   End Sub

   Private Sub setCaption(ob As Object)
    Dim texto As String = selectCaption(dt, ob.Name)
    If texto <> "" Then
    ob.Text = selectCaption(dt, ob.Name)
    'msgbox( ob.Text )
    End If    
   End Sub

   Private Function selectCaption(dt As DataTable, nomC As String) As String
    Dim s As String = ""    
    Dim foundRows() As DataRow
foundRows = dt.Select("NombreControl Like '" & nomC & "%'")
If foundRows.Length = 1 Then s = BlobToString(foundRows(0).Item(2))  
Return s
   End Function  


proyecto en google Docs

Saludos  ;D
Un error se comete al equivocarse.

Keyen Night

#1
Muy bueno, esto es necesario, nuestros programas tienen más oportunidad de progresar mientras más público tengan y eso es igual a tener la aplicación disponible en más lenguajes.

Hace tiempo necesite que una aplicación cubriera varios lenguajes, era por archivos locales, pero sigue el mismo principio; se basaba en un Diccionario String, String que como Key guardaba el nombre del control, como llegar a el y la propiedad a asignarle el Value del Diccionario, quiero decir, como que Key podría ser por ejemplo:

Form1\Contenedor\Button1*Text y Value Texto en Español

De modo que cuando se cargaba el Diccionario que estaba serializado en un archivo, se usaba Split para separar la ruta que lleva al control, usando Find desde la raíz hasta encontrar el Control deseado Form1.Find para obtener el control Contenedor y Contenedor.Find para obtener Button1 luego se asignaba con Reflection la propiedad Text.

Para los textos que no guardaban relación con un Control los guardaba con un Key #0001 por ejemplo y seguía #0002, #0003 de modo que al cargar el Diccionario y aplicar las propiedades se ignorara todo lo que comienza con #.

Tenía muchos Form e infinidad de Controles por lo qué me ayude con este código que generá el Diccionario:

Una que lista todos los controles de un Form y otra que le da el nombre al control en la forma que te mencione antes.

Código (vb.net) [Seleccionar]
   Public Function GenerateTreeName(ByVal x As Control) As String

       GenerateTreeName = x.Name

       Do While x.Parent IsNot Nothing
           x = x.Parent
           GenerateTreeName = x.Name & "\" & GenerateTreeName
       Loop

   End Function

   Public Function ListControls(ByVal x As Control) As List(Of Control)

       ListControls = New List(Of Control)

       Dim Parents As New List(Of Control)

       For Each y As Control In x.Controls
           If y.HasChildren Then
               Parents.Add(y)
           End If
           ListControls.Add(y)
       Next

       For Each y As Control In Parents
           ListControls.AddRange(ListControls(y))
       Next

   End Function


Realmente me pareció la mejor forma y que resume código de manera increíble.
La Fé Mueve Montañas...
                                    ...De Dinero

La programación es más que un trabajo es más que un hobby es una pasión...

Maurice_Lupin

Keyen Night, mi problema fue que al intentar acceder a los elementos de un ToolStrip o MenuStrip utilizando el tipo Control me daba error.

La colección MenuStrip1.Controls no contiene los ToolStripMenuItem sino la colección MenuStrip1.Items, el error que me daba es que los ToolStripMenuItem no son del tipo Control.

Al menos que si hayas logrado acceder a los elementos de un MenuStrip o de un ToolStrip usando el tipo Control, me encantaria ver tu codigo  ;D

Saludos y gracias por el comentario.
Un error se comete al equivocarse.

Keyen Night

#3
Eso me paso también con TabPageControl, eso ya está resuelto en código, es una Clase llamada LanguageFile, estructura y serializa las propiedades que tengas que almacenar en un archivos que contiene información del lenguaje, el autor, y la parte de los datos con contiene el diccionario serializado. Cuando se quiere cambiar de idioma se crea un objeto LanguageFile que apunta hacia un archivo '*.lng', se llama al Sub Apply, el diccionario se deserializa, y se recorre siguiendo el  cada control con Find a través de todos los Parent, una vez que lo encuentra, lee la parte que dice *PROPIEDAD y dependiendo el tipo, lee y asigna el Value del diccionario, de manera distinta, ya que en tiempo de ejecución Reflection te brinda todas las herramientas para jugar con las propiedades de forma no administrada.

Aquí está el código, coloco en la siguiente lista cosas que le faltarían hacerle que me han dado flojera :xD

Desventajas:

  • Obtener objetos Form por su nombre, por ahora se le debe decir a Apply cuales son los Form disponibles y su nombre.
  • Brindar soporte para todos los tipos de array, por ahora solo tiene para Columns y TabPages.

En Value '#D#' queda comprendido como un salto de línea.

Se podría hacer algo con Flags para saber cuando la propiedad a asignar es del tipo Array y tomar las precauciones al colocar Value como valor de la propiedad. Pero como por ahora no me ha servido para lo que quiero me ha dado flojera actualizarla :silbar:

Para el Caso del Tool/MenuStrip se podría crear un Flag especial de modo que en Apply se le trate de una forma particular, probablemente me pondré a hacer eso :laugh: de los Flags resultaría muy útil.

Código (vb.net) [Seleccionar]

Imports System.Runtime.Serialization, System.IO
Imports System.Globalization, System.Reflection
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.Text

<Serializable()> _
Public Class LanguageFile

   Implements ISerializable

   Public Event Applied()

#Region " Delegados "

   Public Delegate Sub SetProperty_Delegate( _
                  ByVal ObjectControl As Control, _
                  ByVal ObjectName As String, _
                  ByVal ObjectValue As Object)

   Public Sub SetProperty( _
                         ByVal ObjectControl As Control, _
                         ByVal ObjectName As String, _
                         ByVal ObjectValue As Object)
       If ObjectControl.InvokeRequired Then
           ObjectControl.Invoke(New SetProperty_Delegate(AddressOf SetProperty), _
                                New Object() {ObjectControl, ObjectName, ObjectValue})
       Else
           ObjectControl.GetType.GetProperty(ObjectName).SetValue( _
                                             ObjectControl, _
                                             ObjectValue, _
                                             Nothing)
       End If
   End Sub

   Public Delegate Function GetProperty_Delegate( _
                     ByVal ObjectControl As Control, _
                     ByVal ObjectName As String) As Object

   Public Function GetProperty(ByVal ObjectControl As Control, _
                         ByVal ObjectName As String) As Object
       If ObjectControl.InvokeRequired Then
           Return ObjectControl.Invoke(New GetProperty_Delegate(AddressOf GetProperty), _
                                New Object() {ObjectControl, ObjectName})
       Else
           Return ObjectControl.GetType.GetProperty(ObjectName).GetValue( _
                                             ObjectControl, _
                                             Nothing)
       End If
   End Function

#End Region

#Region " Private Fields "

   Private _
   _ShortName As String, _
   _Dic As Dictionary(Of String, String), _
   _Author As String

#End Region

#Region " Serializable "

   Protected Sub GetObjectData(ByVal info As System.Runtime.Serialization.SerializationInfo, ByVal context As System.Runtime.Serialization.StreamingContext) Implements System.Runtime.Serialization.ISerializable.GetObjectData

       For Each x As FieldInfo In Me.GetType.GetFields(BindingFlags.NonPublic Or _
                                                       BindingFlags.Instance)
           If x.Name.StartsWith("_") Then
               info.AddValue(x.Name, x.GetValue(Me))
           End If
       Next

       'info.AddValue("_ShortName", _ShortName)
       'info.AddValue("_Author", _Author)
       'info.AddValue("_Dic", _Dic)

   End Sub

   Protected Sub New(ByVal info As SerializationInfo, ByVal context As StreamingContext)

       For Each x As FieldInfo In Me.GetType.GetFields(BindingFlags.NonPublic Or _
                                                       BindingFlags.Instance)
           If x.Name.StartsWith("_") Then
               x.SetValue(Me, info.GetValue(x.Name, x.FieldType))
           End If
       Next

       '_ShortName = info.GetValue("_ShortName", GetType(String))
       '_Author = info.GetValue("_Author", GetType(String))
       '_Dic = info.GetValue("_Dic", GetType(Dictionary(Of String, String)))

   End Sub

#End Region

#Region " Public Constructors "

   Public Sub New(ByVal Buffer As Byte())

       If Buffer.Length > (1024 ^ 2) Then
           Throw New OverflowException()
       Else
           Dim MStream As New MemoryStream

           MStream.Write(Buffer, 0, Buffer.Length)

           MStream.Seek(0, SeekOrigin.Begin)

           Dim BFormatter As New BinaryFormatter

           Dim [Me] As LanguageFile = BFormatter.Deserialize(MStream)

           MStream.Close()
           MStream.Dispose()
           MStream = Nothing

           _Dic = [Me]._Dic
           _ShortName = [Me]._ShortName
           _Author = [Me].Author

           Erase Buffer

       End If

   End Sub

   Public Sub New(ByVal LanguageFile As String)

       If File.Exists(LanguageFile) Then
           Dim LF As New FileInfo(LanguageFile)
           If LF.Length > (1024 ^ 2) Then
               Throw New OverflowException(LanguageFile)
           Else
               Dim MStream As New MemoryStream
               Dim FStream As New FileStream(LanguageFile, FileMode.Open, FileAccess.Read)
               Dim FBuffer As Byte() = New Byte(LF.Length - 1) {}

               FStream.Read(FBuffer, 0, LF.Length)

               FStream.Close()
               FStream.Dispose()
               FStream = Nothing

               MStream.Write(FBuffer, 0, FBuffer.Length)
               MStream.Seek(0, SeekOrigin.Begin)

               Dim BFormatter As New BinaryFormatter

               Dim [Me] As LanguageFile = BFormatter.Deserialize(MStream)

               MStream.Close()
               MStream.Dispose()
               MStream = Nothing

               _Dic = [Me]._Dic
               _ShortName = [Me]._ShortName
               _Author = [Me].Author

               Erase FBuffer

           End If
       Else
           Throw New FileNotFoundException(LanguageFile)
       End If

   End Sub

   Public Sub New(ByVal LanguageFile As String, _
                  ByVal Dic As Dictionary(Of String, String), _
                  ByVal ShortName As String, _
                  ByVal Author As String)
       _Dic = Dic
       _ShortName = ShortName
       _Author = Author

       Dim FStream As New FileStream(LanguageFile, FileMode.Create, FileAccess.Write)
       Dim MStream As New MemoryStream
       Dim BFormatter As New BinaryFormatter
       Dim FBuffer As Byte()

       BFormatter.Serialize(MStream, Me)

       FBuffer = New Byte(MStream.Length - 1) {}

       MStream.Seek(0, SeekOrigin.Begin)

       MStream.Read(FBuffer, 0, MStream.Length)

       MStream.Close()
       MStream.Dispose()
       MStream = Nothing

       FStream.Write(FBuffer, 0, FBuffer.Length)

       FStream.Close()
       FStream.Dispose()
       FStream = Nothing

       Erase FBuffer

   End Sub

#End Region

#Region " ReadOnly Properties "

   Public ReadOnly Property GetString() As Dictionary(Of String, String)
       Get
           Return _Dic
       End Get
   End Property

   Public ReadOnly Property Author() As String
       Get
           Return _Author
       End Get
   End Property

   Public ReadOnly Property Culture() As CultureInfo
       Get
           Return New CultureInfo(_ShortName)
       End Get
   End Property

#End Region

#Region " Public Sub "

   Public Sub Apply()

       For Each x As KeyValuePair(Of String, String) In _Dic
           If Not x.Key.StartsWith("#") Then

               Dim Tree As String = x.Key.Split("*")(0)
               Dim PropertyName As String = x.Key.Split("*")(1)
               Dim Controls As String() = Tree.Split("\")
               Dim CurrentControl As Control = Nothing

               If Controls.Length = 1 Then
                   Select Case Controls(0)
                       Case "Form1"
                           'SetProperty(Form1, PropertyName, x.Value)
                       Case "Form2"
                           'SetProperty(Form2, PropertyName, x.Value)
                   End Select
               Else
                   Select Case Controls(0)
                       Case "Form1"
                           'CurrentControl = Form1
                       Case "Form2"
                           'CurrentControl = Form2
                   End Select
                   For y As Integer = 1 To Controls.Length - 1
                       CurrentControl = CurrentControl.Controls.Find(Controls(y), False)(0)
                   Next
                   If PropertyName.StartsWith("Columns") Then
                       Dim Index As Integer = PropertyName.Replace("Columns(", "").Replace(")", "")
                       CType(GetProperty(CurrentControl, "Columns")(Index), ColumnHeader).Text = x.Value
                   ElseIf PropertyName.StartsWith("TabPages") Then
                       Dim Index As Integer = PropertyName.Replace("TabPages(", "").Replace(")", "")
                       CType(GetProperty(CurrentControl, "TabPages")(Index), TabPage).Text = x.Value
                   Else
                       SetProperty(CurrentControl, PropertyName, x.Value.Replace("#D#", Environment.NewLine))
                   End If
               End If

           End If
       Next

       RaiseEvent Applied()

   End Sub

#End Region

End Class
La Fé Mueve Montañas...
                                    ...De Dinero

La programación es más que un trabajo es más que un hobby es una pasión...