4

I follow the Globalization and localization and Building simple multilingual ASP.NET Core website tutorials to add a language switch for my application.

So, I created a partial view

@using Microsoft.AspNetCore.Builder
@using Microsoft.AspNetCore.Http.Features
@using Microsoft.AspNetCore.Localization
@using Microsoft.AspNetCore.Mvc.Localization
@using Microsoft.Extensions.Options

@inject IViewLocalizer Localizer
@inject IOptions<RequestLocalizationOptions> LocOptions

@{
    var requestCulture = Context.Features.Get<IRequestCultureFeature>();
    var cultureItems = LocOptions.Value.SupportedUICultures
        .Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName })
        .ToList();
}

<div title="@Localizer["Request culture provider:"] @requestCulture?.Provider?.GetType().Name">
    <form id="selectLanguage" asp-controller="Home"
          asp-action="SetLanguage" asp-route-returnUrl="@Context.Request.Path"
          method="post" class="form-horizontal" role="form">
        @Localizer["Language:"] 
        <select name="culture"
                onchange="this.form.submit();"
                asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems"></select>
    </form>
</div>

Added in the footer of the _Layout the

<div class="col-md-6 text-right">
    @await Html.PartialAsync("_SelectLanguagePartial")
</div>

and configure the Startup.cs like this:

services.AddLocalization(options => options.ResourcesPath = "Resources");

services.AddMvc()
    .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
    .AddDataAnnotationsLocalization();

services.Configure<RequestLocalizationOptions>(options =>
{
    var supportedCultures = new[]
    {
        new CultureInfo("es"),
        new CultureInfo("en")
    };

    options.DefaultRequestCulture = new RequestCulture(culture: "es", uiCulture: "es");
    options.SupportedCultures = supportedCultures;
    options.SupportedUICultures = supportedCultures;    

});

I added a Resources folder and in it the

Views.Home.Index.es.resx
Views.Home.Index.en.resx
Views.Shared._Layout.es.resx
Views.Shared._Layout.en.resx

I also did Install-Package Microsoft.AspNetCore.Authentication.Cookies

When I load the Home View I have the Spanish option selected. But when I try to select "English" it loads, but rolls-back the Spanish version, so I can't finally see my content in English. Where is the problem?

serge
  • 13,940
  • 35
  • 121
  • 205

2 Answers2

11

Add an additional answer for those who did not make it work even if you have updated your code with Joe Auddette's answer.

The CookieOptions blocked me a long time to make things work:

[HttpPost]
public IActionResult SetLanguage(string culture, string returnUrl)
{
    Response.Cookies.Append(
        CookieRequestCultureProvider.DefaultCookieName,
        CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
        new CookieOptions
        {
            Expires = DateTimeOffset.UtcNow.AddYears(1),
            IsEssential = true,  //critical settings to apply new culture
            Path = "/",
            HttpOnly = false,
        }
    );

    return LocalRedirect(returnUrl);
}

IsEssential has following comments in source code:

Indicates if this cookie is essential for the application to function correctly. If true then consent policy checks may be bypassed. The default value is false.

and the consent policy is set in startup.cs

services.Configure<CookiePolicyOptions>(options =>
{
    // This lambda determines whether user consent for non-essential cookies 
    // is needed for a given request.
    options.CheckConsentNeeded = context => true;
    options.MinimumSameSitePolicy = SameSiteMode.None;
});
serge
  • 13,940
  • 35
  • 121
  • 205
Dongdong
  • 2,208
  • 19
  • 28
9

Did you add javascript to make the language selector postback?

(function () {
$("#selectLanguage select").change(function () {
    $(this).parent().submit();
});
}());

Did you wire up therequest localization middleware in Configure?

var locOptions= app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
app.UseRequestLocalization(locOptions.Value);

Did you add a method in HomeController like this:

[HttpPost]
public IActionResult SetLanguage(string culture, string returnUrl)
{
    Response.Cookies.Append(
        CookieRequestCultureProvider.DefaultCookieName,
        CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
        new CookieOptions { Expires = DateTimeOffset.UtcNow.AddYears(1) }
    );

    return LocalRedirect(returnUrl);
}
serge
  • 13,940
  • 35
  • 121
  • 205
Joe Audette
  • 35,330
  • 11
  • 106
  • 99
  • I had the first two options missing. The first one was't mentionned in the tutorial, the second one I did't read properly ! Thanks a lot ! The third would thow an exception, not the case :) – serge Jul 24 '17 at 15:03
  • There is just a problem with the `DisplayAttribute` localization... surely is an other story, but it seems that is not working yet... – serge Jul 24 '17 at 16:58
  • https://stackoverflow.com/questions/37833661/asp-net-core-displayattribute-localization – Joe Audette Jul 24 '17 at 17:17
  • My problem was once another one :) I used custom @Html.DisplayShortNameFor(), so, the proposed solution here https://stackoverflow.com/questions/45234670/asp-net-core-shortname-in-the-display-attribute-dataannotations does not take into account the internationalization – serge Jul 24 '17 at 17:25
  • 1
    The "standard" `DisplayNameFor` worked without additional stuff – serge Jul 24 '17 at 17:30