Reputation: 416
Every example I have found, including the official Microsoft documentation on Localization at https://learn.microsoft.com/en-us/aspnet/core/fundamentals/localization?view=aspnetcore-2.1, uses a Controller to perform the action of setting and saving the desired Culture. My ASP.NET Core 2.1 web app is NOT MVC, so does not have a Controller. I have tried several ways to get around this, including adding a dummy Controller to my project, but I still cannot get the Culture switch to work.
My Startup class Configure method contains the following code:
var supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("hi-IN")
};
app.UseRequestLocalization(new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture(DefaultCulture.Name),
// Formatting numbers, dates, etc.
SupportedCultures = supportedCultures,
// UI strings that we have localized.
SupportedUICultures = supportedCultures
});
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseMvc();
The ConfigureServices method contains this code:
// Add the localization services to the services container
services.AddLocalization(options => options.ResourcesPath = "Resources");
// Add MVC Services to the Services Collection.
services.AddMvc()
// Add support for finding localized views, based on file name suffix, e.g. Index.fr.cshtml
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
// Add support for localizing strings in data annotations (e.g. validation messages) via the
// IStringLocalizer abstractions.
.AddDataAnnotationsLocalization();
// Configure supported cultures and localization options
var supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("hi-IN")
};
services.Configure<RequestLocalizationOptions>(options =>
{
// State what the default culture for your application is. This will be used if no specific culture
// can be determined for a given request.
options.DefaultRequestCulture = new RequestCulture(DefaultCulture.Name, DefaultCulture.Name);
// You must explicitly state which cultures your application supports.
// These are the cultures the app supports for formatting numbers, dates, etc.
options.SupportedCultures = supportedCultures;
// These are the cultures the app supports for UI strings, i.e. we have localized resources for.
options.SupportedUICultures = supportedCultures;
});
// Register the email service used for "contacts".
services.AddSingleton<IEmailSender, EmailSender>();
// Configure startup to use the SendGrid options.
services.Configure<AuthMessageSenderOptions>(Configuration);
// Add cross-origin resource sharing services to the specified IServiceCollection.
//
// The Policy specifed as an option will allow any method.
services.AddCors(options => options.AddPolicy("CorsPolicy", b => b.AllowAnyMethod()));
And DefaultCulture is:
DefaultCulture = new CultureInfo(Configuration["Localization:DefaultCulture"]);
Where the settings file contains the string "en-US".
I'm then using the _SelectLanguagePartial.cshtml code from the Localization docs sample:
<div title="@Localizer["Request culture provider:"] @requestCulture?.Provider?.GetType().Name">
<form id="selectLanguage" asp-controller="Home"
asp-action="SetLanguage" asp-route-returnUrl="@returnUrl"
method="post" class="form-horizontal" role="form">
<label asp-for="@requestCulture.RequestCulture.UICulture.Name">@Localizer["Language:"]</label>
<select name="culture" onchange="this.form.submit();" asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems"></select>
</form>
First of all, there is no Controller. How exactly can I implement this functionality in a non-MVC ASP.NET Core web app?
Upvotes: 1
Views: 1902
Reputation: 5719
You don’t have to use controllers, recently I’ve published a step-by-step tutorial to develop multicultural web application with ASP.NET Core Razor Pages; you can find it here:
http://www.ziyad.info/en/articles/10-Developing_Multicultural_Web_Application
I used rout value approach, but you can extend it to use query string, cookie or accepted header value for culture selecting.
In the website you can see a live demo and project source code link on github.
Additionally you may need to check localizing identity error messages as well:
http://ziyad.info/en/articles/20-Localizing_Identity_Error_Messages
I hope it helps :)
[UPDATE]
The sample I've provided is using shared resource files. If you want to use view related resource file approatch, create the resource files for each view/culture inside "Resources" folder and keep the folder structure of resources similar to its related views.
for example, if we have a view named "MyView" inside pages folder:
Pages/MyView.cshtml
The resource files should be like below:
Resources/Pages/MyView.tr-TR.resx
Resources/Pages/MyView.ar-SY.resx
Resources/Pages/MyView.hi-IN.resx
To use localization inside views inject IViewLocalizer
:
@using Microsoft.AspNetCore.Mvc.Localization
@inject IViewLocalizer _loc
<h4>@_loc["My view title"]</h4>
and for the ViewModel/DataAnnotations, create another resource file for each culture:
View model:
Pages/MyViewModel.cshtml.cs
Resource file name:
Resources/Pages/MyViewModel.tr-TR.resx
Resources/Pages/MyViewModel.ar-SY.resx
Resources/Pages/MyViewModel.hi-IN.resx
Fill the resource files with relevant model property display names and data annotation messages, then modify startup.cs file by clearing the shared resource code for DataAnnotations and keep it parameterless:
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddViewLocalization(o=>o.ResourcesPath = "Resources")
// Option A: use this for localization with shared resource
/*
.AddDataAnnotationsLocalization(o=> {
var type = typeof(ViewResource);
var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
var factory = services.BuildServiceProvider().GetService<IStringLocalizerFactory>();
var localizer = factory.Create("ViewResource", assemblyName.Name);
o.DataAnnotationLocalizerProvider = (t, f) => localizer;
})
*/
// Option B: use this for localization by view specific resource
.AddDataAnnotationsLocalization()
.AddRazorPagesOptions(o => {
o.Conventions.Add(new CultureTemplateRouteModelConvention());
});
btw, I've updated the GitHub sample, now it contains "AnotherPage" view localized using view specific resource files.
Upvotes: 0