检测浏览器显示语言

时间:2013-09-16 10:56:25

标签: c# asp.net

使用以下代码

string[] languages = HttpContext.Current.Request.UserLanguages;
string chosenLanguage = languages[0];

如果我安装了3种语言(例如“da(danish)”,“sv(swedish)”和“en(english)”),则语言数组如下所示:

[0]: "en-US"
[1]: "en;q=0.8"
[2]: "da;q=0.6"
[3]: "sv;q=0.4"

即使我将显示语言更改为“丹麦语”而不是“英语”,数组也不会更改任何值。至于我可以阅读其他人写的关于这个主题的内容,[0]值应该是浏览器的选定语言,但它仍然是"en-US"

是否有其他方式来注册浏览器的语言或我做错了什么?

3 个答案:

答案 0 :(得分:17)

在页面指令上设置UICultureCulture对我有用:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1.Default" UICulture="auto" Culture="auto" %>

然后我将我的chrome语言设置为French,并确保重新排序语言 - chrome将最顶层语言作为浏览器的默认语言

然后我用了:

Response.Write(System.Threading.Thread.CurrentThread.CurrentUICulture);

哪个正确地给了我fr

您可以在页面级别或全局see here设置文化。

答案 1 :(得分:4)

我有一个MVC应用程序,不得不以不同的方式处理这个问题。我们的应用程序使用url参数化语言。我可以推荐哪一种,因为接受的答案不可能改为另一种语言。它也可以被不同语言的搜索引擎抓取,并允许用户保存或发送具有特定语言的URL。

但是,在初始请求时我想检测用户语言,现在OP提到它无法更改顺序,这是因为某些浏览器(Chrome)正在确定这一点,无论您设置的是哪种语言。 chrome language selection 如您所见,我将界面语言设置为英语,但为了测试我将德语移到顶部,我只用于翻译,结果:

languages

因此Chrome只会将用户在设置中设置的内容放在首位。大多数用户可能只设置了他们的用户界面语言以及他们想要用于翻译/拼写检查的一些语言。 所以这是我的代码

<强> Global.asax中

protected void Session_Start(Object sender, EventArgs e)
{
    Session["sessionId"] = Session.SessionID;
    Session.Timeout = 120;
    //first point of request, get the user's browser language
    string[] languages = Request.UserLanguages;
    if (languages != null && Session.IsNewSession)
    {
        LanguageEnum requestLanguage = LanguageHelper.GetLanguage(languages);
        if (requestLanguage != LanguageEnum.NL)//NL is default for the sources
        {
            Response.RedirectToRoute("Locolized", new { lang = requestLanguage.ToString().ToLower() });//Locolized is an route name, see below
        }
    }
}

语言助手

public static LanguageEnum GetLanguage(string[] languages)
{
    if (languages == null) return DefaultLanguage;
    LanguageEnum lang = DefaultLanguage;
    bool firstDone = false;
    foreach (string language in languages)
    {
        string realLanguage = Regex.Replace(language, "[;q=(0-9).]", "");
        LanguageEnum givenlang = GetLanguage(realLanguage);//converts it to an enum, overload method.
        //first one should be the used language that is set for a browser (if user did not change it their self).
        //In some browsers their might be multiple languages (for translations)
        if (!firstDone)
        {
            firstDone = true;
            lang = givenlang; 
        }
        else
        {
            //ranking others
            lang = RankLanguage(lang, givenlang);
        }

    }
    return lang;
}

private static LanguageEnum RankLanguage(LanguageEnum existing, LanguageEnum newLnag)
{
    if (existing == LanguageEnum.EN && newLnag != LanguageEnum.EN)
    {
        //everything that is other then english gets a higher rank
        return newLnag;
    }
    //add other usecases here specific to your application/use case, keep in mind that all other languages could pass
    return existing;
}

//below code is for setting the language culture I use, 
//fixed number and date format for now, this can be improved.
//might be if your interests if you want to use parameterized languages

    public static void SetLanguage(LanguageEnum language)
    {
        string lang = "";
        switch (language)
        {
            case LanguageEnum.NL:
                lang = "nl-NL";
                break;
            case LanguageEnum.EN:
                lang = "en-GB";
                break;
            case LanguageEnum.DE:
                lang = "de-DE";
                break;
        }
        try
        {
            NumberFormatInfo numberInfo = CultureInfo.CreateSpecificCulture("nl-NL").NumberFormat;
            CultureInfo info = new CultureInfo(lang);
            info.NumberFormat = numberInfo;
            //later, we will if-else the language here
            info.DateTimeFormat.DateSeparator = "/";
            info.DateTimeFormat.ShortDatePattern = "dd/MM/yyyy";
            Thread.CurrentThread.CurrentUICulture = info;
            Thread.CurrentThread.CurrentCulture = info;
        }
        catch (Exception)
        {

        }
    }

我处理参数化网址的方式可能符合你的兴趣:

<强> RouteConfig.cs 在其他映射下面

routes.MapRoute(
    name: "Locolized",
    url: "{lang}/{controller}/{action}/{id}",
    constraints: new { lang = @"(\w{2})|(\w{2}-\w{2})" },   // en or en-US
    defaults: new { controller = "shop", action = "index", id = UrlParameter.Optional }
);

FilterConfig.cs (可能需要添加,如果是这样,请将FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);添加到Application_start()

中的Global.asax方法
public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new ErrorHandler.AiHandleErrorAttribute());
        //filters.Add(new HandleErrorAttribute());
        filters.Add(new LocalizationAttribute("nl-NL"), 0);
    }
}

最后, LocalizationAttribute

public class LocalizationAttribute : ActionFilterAttribute
{
    private string _DefaultLanguage = "nl-NL";
    private string[] allowedLanguages = { "nl", "en" };

    public LocalizationAttribute(string defaultLanguage)
    {
        _DefaultLanguage = defaultLanguage;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        string lang = (string) filterContext.RouteData.Values["lang"] ?? _DefaultLanguage;
        LanguageHelper.SetLanguage(lang);
    }
}

剩下要做的就是添加资源,这是我写的一个早期的答案,其中涵盖了:https://stackoverflow.com/a/35813707/2901207

答案 2 :(得分:3)

你试过Request.ServerVariables("HTTP_ACCEPT_LANGUAGE") ??

这是我的输出fr-FR,en-US;q=0.5