C# 通过请求动态更改语言资源的好方法
我有一个ASP.NETWebAPI应用程序,它应该对用户的AcceptLanguage头做出适当的反应 目前,字符串存储在resx中,并通过visualstudio生成的类以编译安全的方式进行访问。我想做的是保持当前的方法,并为每个翻译版本的resx创建附属程序集。然后分析用户的Accept Language标头,查看用户接受哪些语言,并从附属程序集中加载请求语言的资源 我想我可以通过在C# 通过请求动态更改语言资源的好方法,c#,asp.net,.net,localization,asp.net-web-api,C#,Asp.net,.net,Localization,Asp.net Web Api,我有一个ASP.NETWebAPI应用程序,它应该对用户的AcceptLanguage头做出适当的反应 目前,字符串存储在resx中,并通过visualstudio生成的类以编译安全的方式进行访问。我想做的是保持当前的方法,并为每个翻译版本的resx创建附属程序集。然后分析用户的Accept Language标头,查看用户接受哪些语言,并从附属程序集中加载请求语言的资源 我想我可以通过在ResourceSet的帮助下创建一组特定于语言的ResourceManager对象来实现所有这些行为,但是这
ResourceSet
的帮助下创建一组特定于语言的ResourceManager
对象来实现所有这些行为,但是这样就不可能保证编译时的安全性,因为Visual Studio会自动更新resx文件的类
动态选择本地化语言资源的最佳方法是什么?您可以编写一个
HttpModule
来检测语言头并设置当前线程区域性
public class LanguageModule : IHttpModule
{
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}
void context_BeginRequest(object sender, EventArgs e)
{
var application = sender as HttpApplication;
var context = application.Context;
var lang = context.Request.Headers["Accept-Language"];
// eat the cookie (if any) and set the culture
if (!string.IsNullOrEmpty(lang))
{
var culture = new System.Globalization.CultureInfo(lang); // you may need to interpret the value of "lang" to match what is expected by CultureInfo
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
}
}
}
ResourceManager
等将从线程区域性中找出要使用的正确本地化版本。通过阅读您的问题,我没有看到ASP.NET不能自动提供的任何内容。您可以将ASP.NET(WebForms或MVC)配置为使用accept language
请求标头,并适当地设置适当的UICulture(这将影响ResourceManager加载的附属程序集)和区域性(这将影响依赖于区域设置的格式和解析,如日期和数字)
public class LanguageModule : IHttpModule
{
public void Dispose()
{
}
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}
void context_BeginRequest(object sender, EventArgs e)
{
var application = sender as HttpApplication;
var context = application.Context;
var lang = context.Request.Headers["Accept-Language"];
// eat the cookie (if any) and set the culture
if (!string.IsNullOrEmpty(lang))
{
var culture = new System.Globalization.CultureInfo(lang); // you may need to interpret the value of "lang" to match what is expected by CultureInfo
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
}
}
}
要将应用程序配置为使用accept language
列表为每个请求同时设置UICulture和Culture(根据),请如下配置您的web.config:
<globalization uiCulture="auto" culture="auto" />
每页还有一个等效的配置设置
然后,按照流程,如果您的应用程序包含匹配区域性的附属程序集(或者,如果没有,则为其父无关区域性),则资源管理器将使用该程序集。如果没有,则将使用默认资源(英语,如果这是您的基本语言)。我查看了IIS中与线程管理相关的答案,据我所知,一个线程可以处理多个请求。看起来可能有冲突。不过,我应该测试一下。正如你在帖子中所说,如果我尝试发送一个接受语言头,像这样:
Accept Language:it,de,en;q=0.5
且ASP.NET无法找到所请求的意大利语资源,它不会尝试下一步使用德语,而是使用中性文化。有没有办法修复此行为?是的,它似乎只考虑accept language标头中的顶级语言(或者至少是有效的.NET区域性名称的顶级语言?)。如果它更聪明一些,并根据本地化是否可用尝试其他方法,那就更好了。但可能无法真正确定本地化的内容(卫星组装方法意味着您可以拥有任何东西,例如,一个dll可以拥有一个德国dll,另一个dll可以拥有一个意大利dll,一个组件可以拥有一堆其他dll,但其他组件却没有),实际上,大多数最终用户可能只关心一个。也就是说,上周我遇到了与您相同的问题,最终实现了此“自动”设置的替换。在我的例子中,它是MVC,我在OnActionExecuting中处理这个问题。要自己完成这一切需要一点工作(您所得到的只是一个带有q语法的头字符串,您还必须对其进行解析和验证,因为.NET不允许任何区域性名称)。最后,我得到了类似于var orderedValidAcceptLanguages=AcceptLanguage.Parse(httpContext.Request.Headers[“Accept Language”])的东西。其中(x=>x.IsValid)代码>我之前已经对Accept编码进行了解析,因此重用它不会有问题。我非常感兴趣的是,您在实际加载资源时使用了什么方法?您是否像我在问题中所说的那样,为不同的文化创建了一组ResourceManager
对象,或者采取了其他方法?虽然我完全同意大多数用户只关心一种语言,但在瑞士或加拿大等国家,他们通常会说几种语言,因此他们可能会选择多种语言。