卫星程序集,ASP.NET语言未更改

5
我正在将一个项目转换为使用卫星程序集。 我创建了一个名为“Resources”的新类库。所有默认资源都在根级别下*.resx。 然后有每个文化的文件夹。
“en /” 使用*.en.resx “en-GB /” 使用*.en-GB.resx 我更改了.resx文件的访问修饰符为“Public”,并更改了这些设置。
BuildAction: EmbeddedResource
CopyToOutputDirectory: CopyAlways

我确保了.resx设计者*.Designer.cs使用"Resources"命名空间。
我将类库添加到ASP.NET MVC应用程序中,在global.asax.cs中设置所需的区域性。
System.Threading.Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-GB");
System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");

我尝试将al.exeResgen.exe命令添加到资源类库的后期生成事件中。

"C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\Resgen.exe" en-GB/MyResourceFile.en-GB.resx "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\al.exe" /t:lib /embed:en-GB/MyResourceFile.en-GB.resources /culture:en-gb /out:Resources.resources.dll

在MVC应用程序的bin/文件夹中,有每种语言的文件夹,每个文件夹里有3个文件:

MyResources.en-GB.Designer.cs, MyResources.en-GB.resx, Resources.resources.dll

根级别只有Resources.dllResources.resources.dll,但默认语言可以正常工作。第二个*.resources.dll是由于后期生成事件引起的。

当我更改CurrentUICulture时,它并不会更改UI语言。在将资源从App_GlobalResources/移动到外部程序集之前,它可以正常工作(例如Razor示例)。

@Resources.MyResources.StringIdentifier 

使用.NET Reflector查看资源.dlls,以下是它们的区别。

Satellite Resources: (Project: Resources)
Resources.en_GB.MyResources.en-GB.resources 
App_GlobalResources: (Project MVCApp)
Namespace.MVCApp.App_GlobalResources.MyResources.en-GB.resources

编辑:

global.asax.cs中设置了CurrentCultureUICulture之后,我手动测试获取一个ResourceManager,它实际上可以成功检索到预期语言的字符串。

            System.Resources.ResourceManager gStrings =
                new System.Resources.ResourceManager("Resources.MyResources", System.Reflection.Assembly.Load("Resources")); // Resources=Project Name
            string test = gStrings.GetString("TestString"); // WORKS IN GLOBAL.ASAX.CS!!!

我在MVC Controller中尝试了相同的测试,但无法正常工作。因此,唯一可以检索ResourceManager的位置是Global.asax.cs。

奇怪的是,在Razor UI的用户界面上进行相同的测试只会返回默认文化的文本! CultureInfo是正确的,但ResourceManager仅在ASP.NET MVC Razor UI中返回默认语言。(这仅用于测试)

    @{  
        System.Globalization.CultureInfo ci = System.Threading.Thread.CurrentThread.CurrentUICulture;
        System.Resources.ResourceManager gStrings =
            new System.Resources.ResourceManager("Resources.MyResource", System.Reflection.Assembly.Load("Resources"));
        string s = gStrings.GetString("Test");    // DOESN'T WORK IN UI
    }

简化版:

将从App_GlobalResources中的资源(.resx)转换为卫星程序集。

问题所在。

我可以手动在global.asax中使用CurrentUICulture语言调用卫星程序集的ResourceManager,它按预期工作,但是相同的测试在UI侧失败,并且在MVC控制器中失败。

默认语言正常工作,那么为什么UI不能切换语言呢?

1个回答

1

如果您最近设置了一个项目,其中国际化的工作几乎像您描述的那样正常运行。

https://github.com/Jacco/Perpetuality

我在作为基础控制器使用的OnAuthorize中通过HTTP请求切换语言:

using Perpetuality.Data;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Security.Principal;
using System.Threading;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;


namespace Perpetuality.Controllers
{
    public partial class BaseController : Controller
    {
        private CultureInfo GetCultureInfo(AuthorizationContext filterContext)
        {
            switch ((string)filterContext.RouteData.Values["language"])
            {
                case "nl":
                    return CultureInfo.CreateSpecificCulture("nl-NL");
                case "en":
                    return CultureInfo.CreateSpecificCulture("en-US");
                case "pt":
                    return CultureInfo.CreateSpecificCulture("pt-PT");
                case "de":
                    return CultureInfo.CreateSpecificCulture("de-DE");
                case "es":
                    return CultureInfo.CreateSpecificCulture("es-ES");
                case "fr":
                    return CultureInfo.CreateSpecificCulture("fr-FR");
                case "it":
                    return CultureInfo.CreateSpecificCulture("it-IT");
                case "jp":
                    return CultureInfo.CreateSpecificCulture("ja-JP");
                default:
                    return CultureInfo.CreateSpecificCulture("en-US");
            }
        }

        protected override void OnAuthorization(AuthorizationContext filterContext)
        {
            Thread.CurrentThread.CurrentCulture = GetCultureInfo(filterContext);
            Thread.CurrentThread.CurrentUICulture = GetCultureInfo(filterContext);

            base.OnAuthorization(filterContext);
        }
    }
}

在我的项目中,RESX文件的指定方式与你们的不同:
BuildAction: EmbeddedResource
CopyToOutputDirectory: DoNotCopy

我在代码中这样访问字符串:

@Resources.Home.Index.FacebookButtonCaption

我没有设置任何构建前或构建后的内容。
在我的项目中,语言始终存在于URL中。这样,如果最初选择的语言不合适,用户可以切换语言。

分享加1。我使用cookie来设置语言,因此Culture仅在登录时设置。在详细调查您的应用程序(以及它是否适用于卫星资源)之前,需要一段时间,感谢您的发布。当在多个项目中使用时,它们有点棘手并需要相当繁琐的细节。 :) - lko
我认为您需要为每个请求设置文化。虽然从cookie中获取也可以。我的资源也在一个单独的库中(我想这就是你所说的“卫星”吧?) - Jacco

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接