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

时间:2015-01-23 20:08:01

标签: c# .net asp.net-mvc azure

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

3 个答案:

答案 0 :(得分:2)

这个问题已在这里得到解答:Asynchrony and thread culture


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

可能的修复 - don't use that .ConfigureAwait(false)或者您必须明确地通过所有调用传递文化,并确保在进行区域设置感知调用之前将其设置回来。

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

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

根据您看到的行为,我猜在初始开始时设置Culture错误,结果您获得了“随机”文化。

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

答案 1 :(得分:1)

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

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

<强>更新

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

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

如果无法做到这一点,则需要OnActionExecuting来设置resource_cultureresource_culture需要是一个线程局部变量才能使其工作。

答案 2 :(得分:0)

如果其他人发生这种情况,我确定了根本原因。我们有一个页面,用户可以通过电子邮件中提供的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);