【问题标题】:Good way to changing language resources dynamically by request根据请求动态更改语言资源的好方法
【发布时间】:2012-06-20 03:37:22
【问题描述】:

我有一个 ASP.NET Web API 应用程序,它应该对用户的 Accept-Language 标头做出适当的反应。

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

我想我可以通过在 ResourceSet 的帮助下创建一组特定于语言的 ResourceManager 对象来自己实现所有这些行为,但是由于 Visual Studio 无法保持编译时安全负责自动更新 resx 文件的类。

动态选择本地化语言资源的最佳方式是什么?

【问题讨论】:

    标签: c# asp.net .net localization asp.net-web-api


    【解决方案1】:

    通过阅读您的问题,我没有看到 ASP.NET 不自动提供的任何内容。您可以将 ASP.NET(无论是 WebForms 还是 MVC)配置为使用 accept-language 请求标头并设置适当的 UICulture(这将影响 ResourceManager 加载哪个附属程序集)和 Culture(这将影响依赖于区域设置的格式和解析例如日期和数字)。

    要将您的应用配置为使用 accept-language 列表为每个请求设置 UICulture 和 Culture(根据 this MSDN page),请像这样配置您的 web.config:

    <globalization uiCulture="auto" culture="auto" />
    

    每页还有一个等效的配置设置。

    然后,根据Resource Fallback 流程,如果您的应用包含匹配文化的附属程序集(或者,如果失败,则为其父中性文化),资源管理器将使用该程序集。如果不是,那么将使用您的默认资源(如果那是您的基本语言,则为英语)。

    【讨论】:

    • 正如您在帖子中所说,如果我尝试发送像这样的 Accept-Language 标头:Accept-Language: it,de,en;q=0.5 并且 ASP.NET 找不到意大利语请求的资源,接下来它不会尝试德语而是退回到中立文化。有什么办法可以解决这个问题?
    • 是的,它似乎只考虑了接受语言标头中的顶级语言(或者至少是有效的 .NET 文化名称的顶级语言?)。如果它更智能并根据本地化是否可用尝试其他方法,那就太好了。但是可能无法真正确定哪些是本地化的(卫星组装方法意味着您可以拥有任何东西,例如,一个 dll 对应一个德语,一个 dll 对应一个意大利语,一个组件对应一个组件,而其他组件则不能)并且实际上,大多数最终用户可能只关心一个。
    • 也就是说,我上周遇到了和你一样的问题,最终实现了这个“自动”设置的替换。就我而言,它是 MVC,我在 OnActionExecuting 中处理了这个问题。自己做这件事有点工作(你得到的只是一个带有 q 语法的标题字符串,你必须解析它并验证它,因为 .NET 不允许任何文化名称)。我最终得到了类似var orderedValidAcceptLanguages = AcceptLanguage.Parse(httpContext.Request.Headers["Accept-Language"]).Where(x =&gt; x.IsValid).OrderByDescending(x =&gt; x.Q).ToList();
    • 我之前已经完成了 Accept-Encoding 的解析,所以重用它不会有问题。我很感兴趣您使用什么方法来实际加载资源?如我的问题中所述,您是否针对不同的文化做了一组 ResourceManager 对象之类的事情,还是采取了其他方法?
    • 虽然我完全同意大多数用户关心单一语言的事实,但在瑞士或加拿大等国家/地区,他们通常会说多种语言,因此他们可能会选择多种语言。
    【解决方案2】:

    您可以编写一个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 等人将从线程文化中找出要使用的正确本地化版本。

    【讨论】:

    • 我查看了与 IIS 中的线程管理相关的this 答案,据我了解,单个线程可以处理多个请求。看起来可能有冲突。不过我应该测试一下。
    猜你喜欢
    • 2015-08-03
    • 1970-01-01
    • 2021-08-21
    • 1970-01-01
    • 1970-01-01
    • 2016-08-19
    • 2016-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多