文化没有应用于多语言网站
我有一个非常不寻常的问题,让我完全难过。 我们有一个多语言网站,所以我们使用资源文件。 但是,像@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_culture
。 resource_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);