Get browser language in ASP.NET Core?
Asked Answered
H

5

24

I am trying to get the default language from the browser and I use the following code to get it:

var languages = HttpContext.Request.UserLanguages;

Since the above is not supported with .NET Core 2 I tested with:

var requestContext = Request.HttpContext.Features.Get<IRequestCultureFeature>();

However, it returns null. What is the correct way or alternative to get the language?

Harquebusier answered 20/3, 2018 at 10:31 Comment(1)
Have you added the localisation middleware?Signore
R
49

IRequestCultureFeature provides the first matched language, which is supported by your application. Declaration of supported languages is defined in Configure() of your Startup class (see example). If you still need all accepted languages as a simple string[] like the older Request.UserLanguages property, then use the HeaderDictionaryTypeExtensions.GetTypedHeaders() extension defined in the Microsoft.AspNetCore.Http namespace:

// In your action method.
var languages = Request.GetTypedHeaders()
                       .AcceptLanguage
                       ?.OrderByDescending(x => x.Quality ?? 1) // Quality defines priority from 0 to 1, where 1 is the highest.
                       .Select(x => x.Value.ToString())
                       .ToArray() ?? Array.Empty<string>();

The array languages contains the list of accepted languages according to the priority parameter q. The language with the highest priority comes first. To get the default language take the first element of the array languages.

As an extension method:

using System.Collections.Generic;
using System.Linq;

using Microsoft.AspNetCore.Http;

public static class HttpRequestExtensions
{
    public static string[] GetUserLanguages(this HttpRequest request)
    {
        return request.GetTypedHeaders()
            .AcceptLanguage
            ?.OrderByDescending(x => x.Quality ?? 1)
            .Select(x => x.Value.ToString())
            .ToArray() ?? Array.Empty<string>();
    }
}
Rooky answered 26/2, 2019 at 1:52 Comment(4)
Upvoting. I don't see why someone downvoted it because this is a good answerHaustorium
@JérômeMEVEL downvote might be revenge, because I downvoted the accepted answer.Rooky
Thanks, this is useful. What I don't understand is why things are so much more complicated in Core??Ambassador
@Mmm, I agree. I would like to know what the documentation says, but it is not easy to find. A lot easier will be to get the language in the client and send it to the server in a custom header, maybe in the same "accept-language" header, but, if NetCore needs that creepy query to read it, I would not mess with whatever NetCore is trying to doParishioner
S
14

You need to add the localisation middleware to be able to get the IRequestCultureFeature feature:

public void Configure(IApplicationBuilder app)
{
    //...

    //Add this:
    app.UseRequestLocalization();

    //...
}

Now in your controller you can request the feature like this:

var requestCulture = Request.HttpContext.Features.Get<IRequestCultureFeature>();
Signore answered 20/3, 2018 at 10:43 Comment(8)
It is not answer. IRequestCultureFeature is not string[].Rooky
@EvgeniNabokov Of course it isn't a string, it's a service that implements the IRequestCultureFeature interface, exactly as OP uses in the question. OP thought it was correct and accepted is as such, so thank you for the downvote!Signore
@Signore How to get the list of accepted languages using this feature? I used to use Request.UserLanguages which is string[].Rooky
@EvgeniNabokov Like I said above, use the requestCulture object. So something like var requestedCulture = requestCulture.RequestCulture;Signore
@EvgeniNabokov And here's a demo in the official sample code. Once again, thanks for the downvote on a perfectly good answer.Signore
@Signore First, from your example is not clear how to get any language from IRequestCultureFeature. Provide more informative example, please. Second, IRequestCultureFeature is not replace for UserLanguages. I have interfaces that consume user languages as string[]. I can't change interfaces and I can't just create an 1-element array from Culture or UICulture (which matches the first supported language), because I need all accepted languages to pass them further. I came to conclusion I have to parse the accept-languages header manually (as written by Carlos Tenorio). That's sad.Rooky
@EvgeniNabokov This answer is a response to the specific question being asked. It's got nothing to do with your code. If you need something else, then that's your problem and I'm not sure why you're taking that frustration out on me. If you bothered to Google, you would also see this is the recommended way to do it too.Signore
@Signore sorry but I must downvote too. You stated in your comment This answer is a response to the specific question being asked but OP clearly asked about the browser language (both in title and body). After some testing I ended up to the conclusion that your answer is giving the user's system language. Carlos's answer is in my opinion the correct oneHaustorium
P
7

You can get the browser language from the Request Headers

Write on your controller:

//For example --> browserLang = 'en-US'
var browserLang= Request.Headers["Accept-Language"].ToString().Split(";").FirstOrDefault()?.Split(",").FirstOrDefault();
Protean answered 18/12, 2018 at 7:20 Comment(1)
Discarding the priority parameter "q" is a bad idea.Rooky
H
0

You have to add the localization middleware to enable parsing of the culture header, and then get the value through IRequestCultureFeature.

Check this link : https://github.com/aspnet/Mvc/issues/3549

Hairstyle answered 20/3, 2018 at 10:42 Comment(0)
B
0

Maybe my solution will be useful to someone. The difference is that if the headers do not have an Accept-Language, the default language is used.

This code for NET 6.

builder.Services.Configure<RequestLocalizationOptions>(config =>
{
    CultureInfo en = new CultureInfo("en");
    CultureInfo ru = new CultureInfo("ru");
    var langs = new List<CultureInfo> { en, ru };
    config.DefaultRequestCulture = new RequestCulture(en);
    config.SupportedCultures = langs;
    config.SupportedUICultures = langs;
});

app.UseRequestLocalization();

public IActionResult Index()
{
    var languageRequest = HttpContext.Features.Get<IRequestCultureFeature>()?.RequestCulture.Culture.Name;

    // use switch with languageRequest or another your logic
}

Also, you can not use builder.Services.Configure, then in languageRequest you will receive the full name of the language. For example: "en-En", "ru-RU" etc...

Butchery answered 18/2, 2022 at 1:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.