Peter Peter - 3 months ago 11
ASP.NET (C#) Question

CurrentThread.CurrentUICulture is set correctly but seems to be ignored by asp.net

Im struggling with gettings the values from the correct strings.txt in my resource files in my \bin folder when switching languages.

I have a domain.com (for English) and a domain.nl (for Dutch). It however doesnt seem to matter which domain I use and how I set the currentUICulture, the language shown to the user is always the same!

[default.aspx.vb]

Partial Class _Default
Inherits System.Web.UI.Page

Shared rm As ResourceManager = HttpContext.Current.Application("RM")

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Label.Text = rm.GetString("homewelcome")
End Sub

Protected Overrides Sub InitializeCulture()
SetLanguage(Request.Url.ToString)
End Sub

Public Shared Sub SetLanguage(ByVal URL As String)
Dim lang As String = ""
If URL.Contains("www.domain.nl") Then
lang = "nl"
ElseIf URL.Contains("www.domain.com") Then
lang = "en"
End If
System.Threading.Thread.CurrentThread.CurrentUICulture = New System.Globalization.CultureInfo(lang)
System.Threading.Thread.CurrentThread.CurrentCulture = System.Globalization.CultureInfo.CreateSpecificCulture(lang)
End Sub
End Class


[global.asax]

Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
Application("RM") = New ResourceManager("strings", Assembly.Load("strings"))
End Sub


In my bin folder I have:

bin\strings.txt
bin\nl\strings.nl.txt
bin\en\strings.en.txt

I generate the dlls like so:

resgen strings.txt strings.resources
al /embed:strings.resources,strings.resources /out:strings.dll
resgen nl\strings.nl.resources
al /embed:nl\strings.nl.resources,strings.nl.resources /out:nl\strings.resources.dll /c:nl
resgen en\strings.en.resources
al /embed:en\strings.en.resources,strings.en.resources /out:en\strings.resources.dll /c:en


Now, all files seem to be created correctly.

However, when I go to the www.domain.com, the values from bin\strings.txt are used and NOT (like I would expect and desire), the values from bin\en\strings.en.txt

Im running on Windows 7 with IIS7.5
When I debugged I found that in my InitializeCulture method:

Protected Overrides Sub InitializeCulture()
SetLanguage(Request.Url.ToString)
End Sub


when I check for the current
System.Threading.Thread.CurrentThread.CurrentUICulture.ToString
its equal to "en", so it seems that the culture is SET correctly, its only that not the correct strings.dll is used.

But there's a more strange things going on: I have this in my default.aspx
<asp:Literal ID="Literal1" runat="server" Text="<%$Resources:lookingfor%>" />



  1. When I aproach www.domain.nl (the Dutch domain!), the Literal1 controls displays the value from "App_LocalResources\default.aspx.en.resx" and the rm.getstring shows me a value from bin\strings.txt
    And when I check the current System.Threading.Thread.CurrentThread.CurrentUICulture.ToString its equal to "nl"

  2. When I aproach www.domain.com (the English domain!), the Literal1 controls displays the value from "App_LocalResources\default.aspx.en.resx" and the rm.getstring shows me a value from bin\strings.txt
    And when I check the current
    System.Threading.Thread.CurrentThread.CurrentUICulture.ToString
    its equal to "en"



What is going on here?

So when using www.domain.nl, the WRONG strings.dll is used, but the CORRECT .resx

Answer

You can use ResourceManager's GetString(string, CultureInfo) overload to get strings in correct language.

BTW. global.asax is probably the better place to set CurrentCulture and CurrentUICulture.

EDIT Providing code sample per Peter's request

Globabal.asax

For starters, I would detect and store culture:

Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
    ' Fires at the beginning of each request '
    Dim culture As CultureInfo
    Dim uri As Uri = Request.Url
    If uri.ToString().Contains("nederlands") Then
        culture = New CultureInfo("nl-NL")
    ElseIf uri.ToString().Contains("polski") Then
        culture = New CultureInfo("pl-PL")
    Else
        culture = New CultureInfo("en-US")
    End If

    Thread.CurrentThread.CurrentCulture = culture
    Thread.CurrentThread.CurrentUICulture = culture
End Sub

Depending on what you want to do, it might not be the best Function to overload, in your case I believe Session_Start is better (that is unless you want to give users an ability to switch language).
Another thing is, I didn't test it with domain names, I used query parameters and haven't validate them properly but it was just for the purpose of example only.

Create App_LocalResources

Instead of instantiating ResourceManager and compiling your resources manually, I can only suggest you to use App_LocalResources. You just need to right-click on your project in the Solution Explorer, choose Add -> Add Asp.Net Folder -> App_LocalResources.

Create resource files

Create appropriately named resource files: Default.aspx.resx, Default.aspx.nl.resx and add the contents you want to localize to them. In my case it was:

Default.aspx.resx (neutral aka fall-back culture resource file)
label1  Some label
label2  Some other label
Default.aspx.nl.resx (Sorry for my poor Dutch)
label1  Dit is een etiket
label2  Dit is ander etiket
Default.aspx.pl.resx
label1  Jakaś tam labelka
label2  Jakaś inna labelka

Default.aspx.vb (code behind)

In code behind you can programmatically modify contents of your web page like this:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    Label2.Text = Me.GetLocalResourceObject("label2")
End Sub 

For many reasons I would not recommend this method (especially it should not be used in page load handler), however it is sometimes needed.

Default.aspx

Finally we are at our beautiful (and very useful) web page:

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title></title>
</head>
<body>

    <form id="form1" runat="server">
    <div>
      <asp:Label ID="Label1" runat="server" Text="<%$ Resources:label1 %>"></asp:Label>
      <br />
      <asp:Label ID="Label2" runat="server" Text="Label"></asp:Label>    
    </div>
    </form>
</body>
</html>

As you can see, you can access the resources with following expression: <%$ Resources:label1 %>. This will give you the string associated with label1 resource key. Important thing to note: runat="server" is not optional.

HTH. You may want to read the tutorial on Asp.Net Localization as well.

Comments