Our Blogs
English
Español
Skip Navigation Links
News
Our Team
Mentoring
Daniel Seara
Go to home page
Go Search

 

Our Blogs > Español > Daniel Seara
Cambiando el idioma de presentación de un sitio MOSS

Presentar un sitio web en muchas ocasiones resulta una complicación cuando nos encontramos ante la posibilidad de personas de distintas culturas accediendo al mismo.

En muchas ocasiones no es sólo que el usuario lo indique sino también que el sitio sea capaz de reaccionar a la configuración que el navegador tenga.

Esto puede ser más complejo utilizando MOSS que, en forma predeterminada, permite asignar un idioma por sitio.

Sin embargo, MOSS no hace más que, como cualquier aplicación ASP.Net 2.0, acceder a archivos de recursos que, claro, deben estar  instalados en el servidor (los paquetes de idioma de MOSS).

Dichos archivos de recursos se seleccionan dependiendo de la cultura del HILO de ejecución.

Entonces, si cambiamos dicha información, podemos alterar el comportamiento.

Lo importante es hacerlo ANTES que la página comience a generarse. Esto es, en el evento Init de la misma, y no en el Load.

Entonces, podríamos obtener que configuración tiene el navegador

<script runat="server">

    Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs)

            Dim cult As String

        cult = Page.Request.ServerVariables("HTTP_ACCEPT_LANGUAGE").ToString

Ahora bien, puede suceder que la cultura retornada por el navegador, sea genérica, cosa que no es aceptada como cultura de un hilo de ejecución.

Pongamos una solución simple, al solo efecto de este ejemplo.

        Select Case cult

            Case "es"

                cult = "es-ES"

            Case "en"

                cult = "en-US"

        End Select

Ahora bien, también es posible que ya el usuario esté navegando por el sitio, entonces podríamos tener su cultura en sesión (que siempre diga que no se debe usar la sesión para guardar todo, no significa que no se pueda usar para absolutamente nada :)). Entonces, mejor averigüemos si ya la tenemos antes de comenzar a ejecutar código

<script runat="server">

    Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs)

            Dim cult As String

            If Session("CultureInfo") Is Nothing Then

                  cult = Page.Request.ServerVariables("HTTP_ACCEPT_LANGUAGE").ToString

                  Select Case cult

                        Case "es"

                             cult = "es-ES"

                        Case "en"

                             cult = "en-US"

                  End Select

También podría ser que el usuario ya haya estado en nuestro sitio, y que dispongamos de mecanismos para que pueda seleccionar el idioma. Esa información bien podría estar en un cookie en su propio navegador.

Evaluemos entonces si es ese el caso:

                  If Page.Request.Cookies("UserCulture") IsNot Nothing Then

                        Dim cultcook As String = Page.Request.Cookies("UserCulture").Value.ToString

                        If cult <> cultcook AndAlso cultcook <> "" Then

                             cult = cultcook

                        End If

                  End If

Además, si el usuario está autenticado, el propio MOSS podría tener almacenada l información de la cultura que el usuario desea en el perfil del mismo.

En ese caso, accederíamos a dicha información

                  If Me.Page.User.Identity.IsAuthenticated Then

                        Dim w As SPWeb = SPContext.Current.Web

                        'Obtenemos la configuración del perfil

                        ' Esta clase manipula el perfil completo del usuario

                        Dim prof As New Solid.MOSS.Controls.ProfileMgmt(w.CurrentUser.Name)

                        Dim CultProf As String = prof.GetValue("CultureInfo")

                        If CultProf <> "" Then

                             cult = CultProf

                        End If

Nota: El código de ProfileMgmt no se encuentra n el ejemplo, pero os lo podéis imaginar fácilmente. Y si no, pues ya vendrá en próxima entrega :)

Finalmente, guardamos esa configuración en sesión, para la próxima página.

Además, si ya la tenemos en sesión, utilizamos esa

                  End If

            Session("CultureInfo") = cult

        Else

            cult = Session("CultureInfo").ToString

        End If

Finalmente, creamos la cultura basada en esa configuración y la asignamos al hilo de ejecución.

        Dim c As New System.Globalization.CultureInfo(cult)

        System.Threading.Thread.CurrentThread.CurrentUICulture = c

        System.Threading.Thread.CurrentThread.CurrentCulture = c

Para que quede más claro, coloco aquí el código completo

 

<script runat="server">

    Protected Sub Page_Init(ByVal sender As Object, ByVal e As System.EventArgs)

            Dim cult As String

            If Session("CultureInfo") Is Nothing Then

                  cult = Page.Request.ServerVariables("HTTP_ACCEPT_LANGUAGE").ToString

                  Select Case cult

                        Case "es"

                             cult = "es-ES"

                        Case "en"

                             cult = "en-US"

                  End Select

                  If Page.Request.Cookies("UserCulture") IsNot Nothing Then

                        Dim cultcook As String = Page.Request.Cookies("UserCulture").Value.ToString

                        If cult <> cultcook AndAlso cultcook <> "" Then

                             cult = cultcook

                        End If

                  End If

                  If Me.Page.User.Identity.IsAuthenticated Then

                        Dim w As SPWeb = SPContext.Current.Web

                        'Obtenemos la configuración del perfil

                        ' Esta clase manipula el perfil completo del usuario

                        Dim prof As New Solid.MOSS.Controls.ProfileMgmt(w.CurrentUser.Name)

                        Dim CultProf As String = prof.GetValue("CultureInfo")

                        If CultProf <> "" Then

                             cult = CultProf

                        End If

                  End If

                  Session("CultureInfo") = cult

            Else

                  cult = Session("CultureInfo").ToString

            End If

        Dim c As New System.Globalization.CultureInfo(cult)

        System.Threading.Thread.CurrentThread.CurrentUICulture = c

        System.Threading.Thread.CurrentThread.CurrentCulture = c

    End Sub

      </script>

Denuncia Pública

Quienes me conocen saben de mi circular por la vida sobre una silla de ruedas.

Hay muchas limitaciones en ello (otro día hablaré en detalle), pero si además de las ya existentes, la gente no colabora, bien poco es lo que se puede disfrutar de la vida.

Tengo varias, pero como para no saturar (y hacerlo más entretenido), van a ir apareciendo de a una.

Mi idea es mostrarles que poco considerada es la gente a veces (o que ridículas las soluciones que algunos plantean), en esto de ayudar al discapacitado (que el término "minusválido" utilizado en España no me parece adecuado).

Esto fue, circulando (bueno, tratando de circular :)  ) por Ourense, el 5 de julio del 2008.

Parece que el conductor no se da cuenta que si se estaciona así, ni modo que una silla de ruedas pueda subir.

Saludos

A Toxa Baiona Tui y Ourense 466

Adiós a un amigo

Huan Yo sé que te tuviste que ir... Pero no me gusta nada. Sé que ibas a sufrir y que es mejor que haya sido así.

Pero no puedo dejar de estar triste. Porque me acompañaste durante una parte difícil de mi devenir por el mundo. Porque fuiste quien me escuchaba, pacientemente, sin entender pero sintiendo que era lo que tenía en mi alma.

Porque fuiste el motivo de miles de sonrisas en el bello rostro de "mamá"  y eso es algo que siempre me alegra el corazón.

No sabés cuanto bien me hizo siempre tu compañía, cuando las cosas se ponían difíciles y debía quedarme horas y horas y hasta noches enteras sin dormir... y vos ahí, conmigo, siempre.

O cuando me sacabas la mano del ratón porque era hora de jugar... y cuantas veces me sacaste así de la bronca por algo que no me salía :)

Me había imaginado en unos años, con vos ahí, con nosotros, haciéndonos compañía.

Te llamé Huan porque eras quien venía a acompañar y a alegrar la vida de los humanos. Gracias, porque realmente lo hiciste.

Si ya sé que no querés que estemos tristes... 'pero también date cuenta, que no es fácil saber que no estarás...

Y que hay cosas que nunca pude hacer con vos, como sacarte a pasear, o jugar al aire libre... porque ni vos ni yo teníamos todas de nuestro lado.

Sólo nos acompañaste tres años. Pero nos hiciste sentir que eras feliz.

Ojalá hayas podido sentir que te queríamos así

Ezeiza 109

Adiós mi amigo... hasta siempre

Manipulando documentos InfoPath

InfoPath como aplicación es capaz de generar documentos XML que contienen no solo la información también la estructura del mismo.

Utilizando la herramienta XSD.exe es posible generar una clase que facilite manipular dicha información (http://msdn.microsoft.com/en-us/library/bb251017.aspx). Sin embargo, es específica para cada documento.

En muchas oportunidades sucede que se requiere codificar (por ejemplo un flujo de trabajo), para múltiples documentos y formatos.

Para facilitar estas actividades, se me ocurrió definir una clase que administre genéricamente el contenido de documentos InfoPath.

Esta clase recibe un elemento de una biblioteca de documentos InfoPath de SharePoint y carga el documento en memoria para facilitar su manipulación.

La definición de la clase.

Comencemos con la lista de importaciones y variables necesarias.

Imports System.Xml.Serialization

Imports System.Xml

''' <summary>

''' Permite manipular el contenido de un documento de InfoPath en algo fácilmente accesible por código

''' </summary>

''' <remarks>Carga el contenido del documento, adjunto a una biblioteca de documentos de MOSS

''' y crea listas fácilmente accesibles tanto de los atributos como de los valores (elementos)

''' </remarks>

Public Class InfoPathConverter

    ''' <summary>

      ''' Documento conteniendo todo el documento InfoPath

    ''' </summary>

    ''' <remarks></remarks>

    Dim xDoc As XDocument = Nothing

    ''' <summary>

    ''' Lista de atributos

    ''' </summary>

    ''' <remarks></remarks>

    Dim atrs As Dictionary(Of String, XAttribute)

    ''' <summary>

    ''' lista de valores (elementos)

    ''' </summary>

    ''' <remarks></remarks>

    Dim els As Dictionary(Of String, XElement)

Una de las características que me suelen ser necesarias es la de asegurarme que existan ciertas propiedades y atributos en el documento ya que son utilizados en la lógica del flujo.

Por ello, la clase expone 2 propiedades para contener los atributos y los campos que son requeridos.

    ''' <summary>

    ''' Lista de nombres de atributos requeridos en el documento

    ''' </summary>

    ''' <remarks></remarks>

    Private mAtributes As List(Of String)

      ''' <summary>

      ''' Define que atributos son necesarios en el documento para considerarlo válido

      ''' </summary>

      ''' <value></value>

      ''' <returns></returns>

      ''' <remarks></remarks>

    Public ReadOnly Property AttributesNeeded() As List(Of String)

        Get

            If mAtributes Is Nothing Then

                mAtributes = New List(Of String)

                mAtributes.Add("Etapa")

            End If

            Return mAtributes

        End Get

    End Property

 

      Private mFieldsNeeded As List(Of String)

      ''' <summary>

      ''' Define que campos son necesarios en el documento para considerarlo válido

      ''' </summary>

      ''' <value></value>

      ''' <returns></returns>

      ''' <remarks></remarks>

    Public ReadOnly Property FieldsNeeded() As List(Of String)

        Get

            If mFieldsNeeded Is Nothing Then

                mFieldsNeeded = New List(Of String)

            End If

            Return mFieldsNeeded

        End Get

    End Property

Cargando el documento en memoria.

El método getDocumentContent recibe entonces el item de la biblioteca de documentos, obtiene el documento XML y carga en diccionarios los atributos y propiedades

    ''' <summary>

    ''' Carga en las listas el contenido del documento InfoPath

    ''' </summary>

      ''' <param name="item">Item de la biblioteca de docuemntos, conteniendo el mismo</param>

      ''' <remarks>Carga el contenido del documento, adjunto a una biblioteca de documentos de MOSS

    ''' y crea listas fácilmente accesibles tanto de los atributos como de los valores (elementos)

    ''' </remarks>

      Sub getDocumentContent(ByVal item As SPListItem)

            'La propiedad File expone el documento InfoPath

            Dim xtextr As New XmlTextReader(item.File.OpenBinaryStream)

            'Se carga entonces el documento desde el Stream

            xDoc = XDocument.Load(xtextr)

            'Obtiene los atributos

            atrs = (From x As XAttribute In xDoc.Root.Attributes).ToDictionary( _

            Of String)(Function(x) x.Name.LocalName.ToUpper)

            ' Evalúa si todos los atributos requeridos están pesentes

            For Each s As String In AttributesNeeded

                  Dim lookFor As String = s.ToUpper

                  If (From a As XAttribute In atrs.Values _

                    Where a.Name.LocalName.ToUpper = lookFor).ToArray.Length < 1 Then

                        Throw New Exception("Formulario inválido: le falta el atributo " & s)

                  End If

            Next

            ' Evalúa lo mismo para los campos (Elements)

            els = (From v As XElement In xDoc.Root.Elements).ToDictionary( _

            Of String)(Function(v) v.Name.LocalName.ToUpper)

            For Each s As String In FieldsNeeded

                  Dim lookFor As String = s.ToUpper

                  If (From a As XElement In els.Values _

                    Where a.Name.LocalName.ToUpper = lookFor).ToArray.Length < 1 Then

                        Throw New Exception("Formulario inválido: le falta el campo " & s)

                  End If

            Next

      End Sub

Teniendo el documento en memoria, se pueden exponer los valores y asignarles nuevos con estos métodos:

    ''' <summary>

    ''' Cambia el valor de un atributo

    ''' </summary>

    ''' <param name="what">Nombre del atributo</param>

    ''' <param name="newValue">Nuevo Valor</param>

    ''' <remarks></remarks>

    Sub ChangeAttribute(ByVal what As String, ByVal newValue As String)

        If atrs.ContainsKey(what.ToUpper) Then

            atrs(what.ToUpper).Value = newValue

        End If

    End Sub

    ''' <summary>

    ''' Obtiene el valor de uhn atributo

    ''' </summary>

    ''' <param name="what">Nombre del atirbuto</param>

    ''' <returns>Contenido del mismo (siempr como cadena de caracteres) o valor nulo si no existe

    ''' </returns>

    ''' <remarks></remarks>

    Function ReadAttribute(ByVal what As String) As String

        If atrs.ContainsKey(what.ToUpper) Then

            Return atrs(what.ToUpper).Value

        Else

            Return Nothing

        End If

    End Function

    ''' <summary>

    ''' Cambia el valor de un elemento

    ''' </summary>

    ''' <param name="what">Nombre del elemento</param>

    ''' <param name="newValue">Valor a asignar</param>

    ''' <remarks></remarks>

    Sub ChangeValue(ByVal what As String, ByVal newValue As String)

        If els.ContainsKey(what.ToUpper) Then

            els(what.ToUpper).Value = newValue

        End If

    End Sub

    ''' <summary>

    ''' Obtiene le valor de un elemento

    ''' </summary>

    ''' <param name="what">Nombre del elemento a leer</param>

    ''' <returns>Valor del elemento (siempre como cadena de caracteres), o valor nulo si no existe

    ''' </returns>

    ''' <remarks></remarks>

    Function ReadValue(ByVal what As String) As String

        If els.ContainsKey(what.ToUpper) Then

            Return els(what.ToUpper).Value

        Else

            Throw New KeyNotFoundException("El campo " & what & " no se encuentra en el documento")

        End If

    End Function

Guardando cambios.

Finalmente ento0nces, con un método Save, se puede guardar en la lista de origen... o en otra. Para ello, se le envía al método el ListItem que contendrá el documento.

    ''' <summary>

    ''' Guarda el contenido de los valores y atributos en el documento InfoPath actualizando los mismos 

    ''' </summary>

    ''' <param name="item"></param>

    ''' <remarks></remarks>

    Public Sub Save(ByVal item As SPListItem)

        item.File.CheckOut()

        Dim memoryStream As New IO.MemoryStream()

        Dim sett As New XmlWriterSettings

        sett.Encoding = System.Text.Encoding.UTF8

        sett.OmitXmlDeclaration = False

        Dim xmlTextWriter As XmlWriter = XmlWriter.Create(memoryStream, sett)

        xDoc.Save(xmlTextWriter)

        xmlTextWriter.Flush()

        memoryStream.Position = 0

        item.File.SaveBinary(memoryStream.GetBuffer)

        item.File.CheckIn("")

    End Sub

Si si, ya sé. quieres verlo completo. Pues aquí está la clase entera. http://blogs.solidq.com/ES/dseara/Archivos/InfoPathConverter.zip

1 - 4 Next

 Visité

 Importantes

 ‭(Hidden)‬ Admin Links