19

By using the following code

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

if I have installed 3 languages (ex. "da (danish)", "sv (swedish)" and "en (english)"), then the languages array looks like this:

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

Even if I change the display language to "Danish" instead of "English" then the array doesn't change any of the values. As far as I can read from what other people have written about this subject, the [0] value should be the chosen language of the browser, but it is still "en-US".

Is there some other way to register the language of the browser or am I doing something wrong?

skeletank
  • 2,880
  • 5
  • 43
  • 75
Loyalar
  • 2,131
  • 4
  • 24
  • 44
  • 3
    What browser are you using? The Browser UI language and the accepted languages are typically different settings. – Cristian Lupascu Sep 16 '13 at 11:03
  • Can you try setting the Culture info of the Page - [How to: Set the Culture and UI Culture for ASP.NET Web Page Globalization](http://msdn.microsoft.com/en-us/library/bz9tc508.ASPX) – Carbine Sep 16 '13 at 11:07
  • I have tried the code in both Opera 12.16, IE9 and Chrome 29.0. They all say the same. – Loyalar Sep 16 '13 at 11:07

3 Answers3

23

Setting the UICulture and Culture on the page directive worked for me:

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

I then set my chrome language to French and made sure to re-order the languages - chrome will take the topmost language as default for the browser.

I then used:

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

Which correctly gave me fr

You can set the culture on the page level or globally, see here.

DGibbs
  • 14,316
  • 7
  • 44
  • 83
  • 1
    That worked! Fantastic, thanks. I wonder why chrome will take the topmost language instead of the current display language, but I guess that's just the way it's made. I tested it again in the other browsers, and it worked perfectly. – Loyalar Sep 16 '13 at 11:24
  • 1
    Glad to hear it, happy to help! – DGibbs Sep 16 '13 at 11:24
  • https://support.google.com/chromebook/answer/1059490 Chrome documentation for taking top most most language as the default language for websites. Very un-user friendly by Google. You would think when you selected reload browser or checking default it would move it to the top for you. – Phillip Dec 03 '18 at 20:27
8

I have an MVC application and had to deal with this in a different way. Our application is using url parameterized languages. Which I can recommend because changing to another language is not possible for the accepted answer. It also became crawlable by search engines in different languages and allows the user to save or send a URL with a specific lang.

But, on initial request I would like to detect the user language, now the OP mentioned it could not change the order, that is because some browsers (Chrome) are determining this, regardless of the language you have set. chrome language selection As you can see I have the interface language set to English, but to test I moved German to the top which I only use for translation, result:

languages

So Chrome just puts on top whatever the user has set in the settings. Most users will probably only have set their user interface language their and some languages they want to use for translations/spellchecks. So here is my code

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
        }
    }
}

Language Helper

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)
        {

        }
    }

The way I handle parameterized urls might be of your interest:

RouteConfig.cs Below the other mappings

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 (might need to be added, if so, add FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); to the Application_start() method in 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);
    }
}

And finally, the 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);
    }
}

What is left to do is add Resources, here is an earlier answer I wrote that covers that: https://stackoverflow.com/a/35813707/2901207

CularBytes
  • 9,924
  • 8
  • 76
  • 101
3

Have you tried Request.ServerVariables("HTTP_ACCEPT_LANGUAGE") ??

here is my output fr-FR,en-US;q=0.5

Dhaval
  • 2,801
  • 20
  • 39
  • 2
    `HttpRequest.UserLanguages` takes its value from this so it would be no different. – DGibbs Sep 16 '13 at 11:18
  • The response I get from that is `"en-US,en;q=0.8,da;q=0.6,sv;q=0.4"`, which is pretty much the same, unfortunately. – Loyalar Sep 16 '13 at 11:18
  • in my case when i moved up french language in my IE .. Request.ServerVariables["HTTP_ACCEPT_LANGUAGE"] does show "fr" first and then "en" in Request.ServerVariables["HTTP_ACCEPT_LANGUAGE"] – Dhaval Sep 16 '13 at 11:20