多语言网站未应用文化

Culture not being applied in multilingual site

我有一个非常不寻常的问题,让我完全难住了。我们有一个多语言网站,因此我们使用资源文件。但是,我们的视图上的每段文本都像 <a href="#">@TextResources.my_key</a> 一样被烧毁,将被本地化为一种随机文化。这只发生在我的 Azure 部署上,我无法在本地复制。

更神秘的是,有一点文字总是尊重我的文化变化。该文本通过方法调用检索:

<a href="#">@.ConfigUtils.getTerms()</a>

方法是:

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

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

我们所有的控制器都继承自一个基本控制器,我们在其中覆盖 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() 在动作之前执行,所以我认为这将是放置文化管理代码的合适位置。还有其他更好的地方吗?

更新

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

更新 2 根据@RichardSchneider 的要求,自动生成的 TextResources 代码如下:

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

该方法之所以有效,是因为它使用了尊重当前文化的ResourceManager

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

更新

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

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

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

这里已经回答了问题:


一个可能的选择是您在代码中使用 async.ConfigureAwait(false)awiat 之后的结果代码(获得 text/renders 视图)从它恰好执行的线程中获取随机文化,而不是您希望在操作过滤器的同步部分中设置的文化。

可能的修复 - don't use that .ConfigureAwait(false) 或者如果您必须通过所有调用显式传递区域性,并确保在进行语言环境敏感调用之前将其设置回去。

更遥远的可能性:假设您使用默认资源文件生成来使其在 ASP.Net 应用程序中正常运行,您应该

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

根据您看到的行为,我猜某些东西在初始启动时设置了 Culture 错误,结果您获得了 "random" 文化。

要调试,请尝试检查 Culture 属性 的值 - 应该为空。

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

/report/download?id=123&lang=de

在controller action中,原作者在我们的资源对象上设置了文化,而不是线程:

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