CurrentThread.CurrentUICulture设置正确但似乎被asp.net忽略

时间:2011-04-28 09:55:25

标签: .net asp.net vb.net localization internationalization

在切换语言时,我很难从我的\ bin文件夹中的资源文件中获取正确的strings.txt中的值。

我有一个domain.com(英语)和domain.nl(荷兰语)。然而,似乎无论我使用哪个域以及如何设置currentUICulture,显示给用户的语言总是相同的!

[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

在我的bin文件夹中,我有:

仓\ strings.txt BIN \ NL \ strings.nl.txt BIN \ EN \ strings.en.txt

我像这样生成dll:

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

现在,所有文件似乎都是正确创建的。

然而,当我去www.domain.com时,bin \ strings.txt中的值被使用而NOT(就像我期望和期望的那样),来自bin \ en \ strings.en.txt的值< / p>

我在带有IIS7.5的Windows 7上运行 当我调试时,我发现在我的InitializeCulture方法中:

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

当我检查当前System.Threading.Thread.CurrentThread.CurrentUICulture.ToString它等于“en”时,所以看起来文化设置正确,它只是没有使用正确的strings.dll。

但是有一些更奇怪的事情发生了:我在default.aspx <asp:Literal ID="Literal1" runat="server" Text="<%$Resources:lookingfor%>" />

中有这个
  1. 当我接近www.domain.nl(荷兰域名!)时,Literal1控件显示“App_LocalResources \ default.aspx.en.resx”中的值,rm.getstring显示bin中的值\ strings.txt 当我检查当前的System.Threading.Thread.CurrentThread.CurrentUICulture.ToString时它等于“nl”

  2. 当我接近www.domain.com(英文域名!)时,Literal1控件显示“App_LocalResources \ default.aspx.en.resx”中的值,rm.getstring显示bin中的值\ strings.txt 当我检查当前System.Threading.Thread.CurrentThread.CurrentUICulture.ToString时它等于“en”

  3. 这里发生了什么?

    因此,当使用www.domain.nl时,使用了WRONG strings.dll,但是使用了CORRECT .resx

2 个答案:

答案 0 :(得分:3)

您可以使用ResourceManager的GetString(string, CultureInfo)重载来获取正确语言的字符串。

顺便说一句。 global.asax可能是设置CurrentCulture和CurrentUICulture的更好地方。

编辑根据Peter的请求提供代码示例

Globabal.asax

首先,我会发现并存储文化:

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

根据你想做的事情,它可能不是最好的重载功能,在你的情况下我相信Session_Start更好(除非你想让用户能够切换语言)。<登记/> 另一件事是,我没有用域名测试它,我使用了查询参数并且没有正确验证它们,但它仅仅是为了举例的目的。

创建App_LocalResources

我不建议实例化ResourceManager并手动编译资源,而是建议您使用App_LocalResources。您只需在解决方案资源管理器中右键单击您的项目,选择添加 - &gt;添加Asp.Net文件夹 - &gt; App_LocalResources文件。

创建资源文件

创建适当命名的资源文件:Default.aspx.resx,Default.aspx.nl.resx并将要本地化的内容添加到它们。就我而言,它是:

Default.aspx.resx(中性又称后备文化资源文件)
label1  Some label
label2  Some other label
Default.aspx.nl.resx(对不起我的可怜荷兰人)
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(代码隐藏)

在后面的代码中,您可以通过编程方式修改网页内容,如下所示:

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

由于很多原因,我不推荐这种方法(特别是它不应该在页面加载处理程序中使用),但有时需要它。

Default.aspx的

最后,我们在我们漂亮(且非常有用)的网页上:

<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>

如您所见,您可以使用以下表达式访问资源:<%$ Resources:label1 %>。这将为您提供与label1资源键关联的字符串。需要注意的重要事项:runat =“server”不是可选的。

HTH。您可能还想阅读the tutorial on Asp.Net Localization

答案 1 :(得分:0)

使用文化&amp; UICulture页面属性:

VB:

    UICulture = "en-US"
    Culture = "en-US"

    Dim cultureInfo As Globalization.CultureInfo = Globalization.CultureInfo.CreateSpecificCulture("en-US")

    Threading.Thread.CurrentThread.CurrentCulture = cultureInfo
    Threading.Thread.CurrentThread.CurrentUICulture = cultureInfo

C#:

        UICulture = "en-US";
        Culture = "en-US";    
        Globalization.CultureInfo  cultureInfo =  Globalization.CultureInfo.CreateSpecificCulture("en-US");

        Threading.Thread.CurrentThread.CurrentCulture = cultureInfo;
        Threading.Thread.CurrentThread.CurrentUICulture = cultureInfo;


Protected Overrides Sub InitializeCulture()
Dim ui As String = String.Empty

If String.IsNullOrWhiteSpace(Request.QueryString("UI")) Then
    'ui = "en-US"
    If Not Session("UI") Is Nothing Then
        ui = Session("UI")
    Else
        ui = "en-US"
    End If
Else
    ui = Request.QueryString("UI")
End If

UICulture = ui
Culture = ui

Dim cultureInfo As Globalization.CultureInfo = Globalization.CultureInfo.CreateSpecificCulture(ui)

Threading.Thread.CurrentThread.CurrentCulture = cultureInfo
Threading.Thread.CurrentThread.CurrentUICulture = cultureInfo

MyBase.InitializeCulture()
End Sub

我通过Session和QueryString传递UI值,如果UI没有值我将其设置为“en-US”