Inloggen
 
 
 
 
    
Localization in ASP.NET 2.0 using a database and adapters
Location: BlogsFerry Onderwater - Developer    
Posted by: Ferry Onderwater 27-4-2007 12:53
ASP.NET 2.0 offers 'out-of-the-box' localization. It uses resource-files (xml). It is possible to use a database instead (see the article of Michèle Leroux Bustamante, mentioned below the blog). A few days earlier I looked a bit to adapters so I got the crazy idea to add those two pieces together. My prime-directive was: Make code localized with as less changes in the (existing) source as possible. UPLOADTEMPLATE
We start with a simple page with two controls: a dropdownlist with the languages and a label.
The languages are Nederlands, English and Deutsch. The text we want to show on the label is a simple 'Hello'.

So really nothing special. Since we don't want to change a lot of code I choose not to create my own label-control, but instead use an adapter to 'overwrite' the standard functionality.
To do this I create a browserfile:

Code:
<browsers>
    <browser refID="Default">
        <controlAdapters>
            <adapter controlType="System.Web.UI.WebControls.Label"
                     adapterType="Arcencus.LabelAdapter" />
        </controlAdapters>
    </browser>

    <browser id="W3C_Validator" parentID="default">
        <identification>
            <userAgent match="^W3C_Validator" />
        </identification>
        <capabilities>
            <capability name="browser"              value="W3C Validator" />
            <capability name="ecmaScriptVersion"    value="1.2" />
            <capability name="javascript"           value="true" />
            <capability name="supportsCss"          value="true" />
            <capability name="supportsCallback"     value="true" />
            <capability name="tables"               value="true" />
            <capability name="tagWriter"            value="System.Web.UI.HtmlTextWriter" />
            <capability name="w3cdomversion"        value="1.0" />
        </capabilities>
    </browser>
</browsers>


In the browserfile we state when using the control 'System.Web.UI.WebControls.Label' we want to use the adapter 'Arcencus.LabelAdapter'.

Next step is to create the adapter. For this we need to create a file in the App_Code map, a 'generic' adapter which inherits from System.Web.UI.Adapters.ControlAdapter. This is our LabelAdapter. Since we don't have to worry about databinding (it's a label) the only thing to do is overriding the render-method. We use one extra function to retreive the actual text to show from a database.
The whole code for the adapter is:

Code:
Imports System
Imports System.Data
Imports System.Configuration
Imports System.IO
Imports System.Web
Imports System.Web.Security
Imports System.Web.UI
Imports System.Web.UI.WebControls
Namespace Arcencus
    Public Class LabelAdapter
        Inherits System.Web.UI.Adapters.ControlAdapter

        Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
            If TypeOf Control Is Label Then
                Dim lb As Label = CType(Control, Label)
                If (Not String.IsNullOrEmpty(lb.Text)) Then
                    Dim term As String = GetTerm(lb.Text, HttpContext.Current.Session("Culture"))
                    If String.IsNullOrEmpty(term) Then
                        MyBase.Render(writer)
                    Else
                        writer.Write(term)
                    End If
                End If
            Else
                MyBase.Render(writer)
            End If
        End Sub

        Private Function GetTerm(ByVal Text As String, ByVal Culture As String) As String
            Dim sconn As New SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings("GlobalizationConnectionString").ConnectionString)
            Dim scomm As New SqlClient.SqlCommand("SELECT TOP 1 Text FROM Terms WHERE Value = @Value AND Culture = @Culture", sconn)
            With scomm.Parameters
                .AddWithValue("@Value", Text)
                .AddWithValue("@Culture", Culture)
            End With
            Dim _result As String
            sconn.Open()
            _result = scomm.ExecuteScalar
            sconn.Close()
            Return _result
        End Function
    End Class
End Namespace


First we check if the control is really a label. Then we check if the text-property of the label is filled. If so, we retreive the translation, based on this text and the culture (see below). If it isn't found, we simply render the original text. If found, we write the translation. If the control wasn't a label, call the original render-method.

So without changing the aspx it is now localizable Smile

Ok, the culture. In this sample I let the user choose, so no Culture or UICulture settings are used (which obviously is also possible).
When the dropdownlist is used I simply change a session-variable, that's all. And with load off the dropdownlist I also set the session-variable (for init-phase).

The code:
Code:
Partial Class _Default
    Inherits System.Web.UI.Page

    Protected Sub DropDownList1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles DropDownList1.SelectedIndexChanged, DropDownList1.Load
        Session("Culture") = DropDownList1.SelectedValue
    End Sub
End Class


Ofcourse there are many ways to enhance this code. The use of the original text as key to find a translation is at least doubtfull but hey, it's just a prototype Smile

Have fun with this code and don't forget to update me when you use and enhance the code!

Ferry

P.S. The VS.NET 2005 code is attached to this post. In the solution you will also find a SQL-script to create the used db + data.

Bijlagen:
Globalization.rar 5 KB

Permalink |  Trackback
  
 
Weblogs
    
Archief
    
Zoeken
    
 
 
 
 
Copyright 2006-2009 by Arcencus
Privacy Statement | Terms Of Use