多语言网站未应用文化
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_culture
。 resource_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);
我有一个非常不寻常的问题,让我完全难住了。我们有一个多语言网站,因此我们使用资源文件。但是,我们的视图上的每段文本都像 <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_culture
。 resource_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);