【问题标题】:CurrentThread.CurrentUICulture is set correctly but seems to be ignored by asp.netCurrentThread.CurrentUICulture 设置正确,但似乎被 asp.net 忽略
【发布时间】:2011-04-28 09:55:25
【问题描述】:

在切换语言时,我正在努力从我的 \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 文件夹中:

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 中的值,而不是(如我所期望的那样) bin\en\strings.en.txt 中的值

我在带有 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”

这是怎么回事?

所以在使用 www.domain.nl 时,使用了错误的 strings.dll,但使用了正确的 .resx

【问题讨论】:

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


    【解决方案1】:

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

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

    编辑根据彼得的要求提供代码示例

    全球.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

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

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

    默认.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>
    

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

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

    【讨论】:

    • 您能否提供一个代码示例,说明您将如何做到这一点?因为我已经为此苦苦挣扎了至少 2 周。尝试将其放置在 Sub Session_OnStart(ByVal sender As Object, ByVal e As EventArgs) 但不好。实际上,我不想每次调用 Getstring 方法时都传递文化...:)
    • 谢谢,这就是诀窍! ps:我没有注意到你已经在这里回答了......对不起。
    【解决方案2】:

    使用文化和 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”

    【讨论】:

    • 您提到: UICulture = "en-US" 会从 default.aspx.en.resx 读取值吗?另外,你会在哪里添加这些代码行?很抱歉我的所有问题,但我已经为此苦苦挣扎了至少 2 周但没有成功......:(
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-24
    • 2021-10-28
    • 2016-09-30
    • 2012-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多