文化没有应用于多语言网站

我有一个非常不寻常的问题,让我完全难过。 我们有一个多语言网站,所以我们使用资源文件。 但是,像@TextResources.my_key这样的视图中的每一段文本都将被本地化为随机文化。 这只发生在我的Azure部署上,我无法在本地重现。

更令人陌生的是,有一点文字始终尊重我的文化变化。 通过方法调用检索该文本:

 @.ConfigUtils.getTerms() 

方法是:

 public static string getTerms() { string key = GetKeyFromDb(CONSTANTS.TERMS); if (!string.IsNullOrEmpty(key)) { return TextResources.ResourceManager.GetString(key); 

我还在读取我们的资源文件,但在这种情况下,它正在根据需要进行本地化! 是否在视图中读取资源文件之后应用了文化,但是在调用此方法之前?!

我们所有的控制器都从一个基本控制器inheritance,我们重写OnActionExecuting()以应用我们的文化:

 protected override void OnActionExecuting(ActionExecutingContext filterContext) { ContextModel ctx = (ContextModel) Session["ContextModel"]; // Set the correct localization according to the value set by the user if (ctx != null && ctx.UserLanguageId != null){ Thread.CurrentThread.CurrentUICulture = new CultureInfo (ctx.UserLanguageId); Thread.CurrentThread.CurrentCulture = new CultureInfo(ctx.UserLanguageId); } } 

在我开始将文化管理代码移动到不同位置并重新部署到Azure以期解决问题之前,我希望有人想到为什么只有通过方法调用检索的文本才会被本地化。

OnActionExecuting()在操作之前执行,所以我认为这将是放置文化管理代码的适当位置。 还有其他地方会更好吗?

UPDATE

看起来这个问题在部署后出现,但可以通过重新启动云服务来解决。

更新2 Per @ RichardSchneider的请求,自动生成的TextResources代码如下:

 public static string my_key{ get { return ResourceManager.GetString("my_key", resourceCulture); } } 

这里已经回答了这个问题: 异步和线程文化


一种可能的选择是在代码中使用async.ConfigureAwait(false) 。 作为awiat之后的结果代码(获取文本/渲染视图)从它碰巧执行的线程中获取随机文化而不是您希望在动作filter中的同步部分中设置的文本。

可能的修复 – 不要使用.ConfigureAwait(false)或者如果你必须通过所有调用显式传递culture,并确保在进行locale-sensetive调用之前将其设置回来。

更远的可能性:假设你使用默认资源文件生成它在ASP.Net应用程序中的正常function你应该

  • 设置CurrentUICulture
  • 确保生成的资源管理器的Culture属性设置为null

基于你看到的行为,我猜想在初始阶段就会出现Culture错误,因此你会得到“随机”的文化。

要调试尝试检查Culture属性的值 – 应该为null。

该方法有效,因为它使用尊重当前文化的ResourceManager

TextResources.my_key失败,因为它(很可能)仅在第一次使用时被赋值一次。

更新

my_key的自动生成代码将文化信息传递给ResourceManager.GetString 。 我建议修改autogenerator以使用一个参数的重载来生成:

 public static string my_key{ get { return ResourceManager.GetString("my_key"); } } 

如果这不可能,那么您需要OnActionExecuting来设置resource_cultureresource_culture将需要是一个线程局部变量才能使其工作。

如果这发生在其他人身上,我确定了根本原因。 我们有一个页面,用户可以通过电子邮件中提供的URL下载报告。 该URL包含用于本地化的语言查询字符串变量:

/报告/下载?ID = 123&LANG = DE

在控制器操作中,原作者在我们的资源对象上设置文化,而不是线程:

 TextResources.Culture = new CultureInfo("de"); 

查看元数据:

 [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] public class TextResources { public static CultureInfo Culture { get; set; } 

因此,在我们的视图中应用本地化时,似乎此属性优先于线程文化。 由于该属性是静态的,因此无论在为报告提供服务的Azure实例中,它都是全局应用的。 因此,当人们以各种语言下载这些报告时,效果似乎是随机的。

我承认我仍然不清楚为什么以下总是尊重线程文化:

 public static string getTerms() { string key = GetKeyFromDb(CONSTANTS.TERMS); if (!string.IsNullOrEmpty(key)) { return TextResources.ResourceManager.GetString(key);