Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过请求动态更改语言资源的好方法_C#_Asp.net_.net_Localization_Asp.net Web Api - Fatal编程技术网

C# 通过请求动态更改语言资源的好方法

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对象来实现所有这些行为,但是这

我有一个ASP.NETWebAPI应用程序,它应该对用户的AcceptLanguage头做出适当的反应

目前,字符串存储在resx中,并通过visualstudio生成的类以编译安全的方式进行访问。我想做的是保持当前的方法,并为每个翻译版本的resx创建附属程序集。然后分析用户的Accept Language标头,查看用户接受哪些语言,并从附属程序集中加载请求语言的资源

我想我可以通过在
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
对象,或者采取了其他方法?虽然我完全同意大多数用户只关心一种语言,但在瑞士或加拿大等国家,他们通常会说几种语言,因此他们可能会选择多种语言。