AspNetCore Internationalization Fundamentals
- Terms
- IStringLocalizer
- IHtmlLocalizer
- IStringLocalizerFactory
- Shared Resources
- IViewLocalizer
- DataAnnotations Localization
- Configuring Localization Services
- SupportedCultures and SupportedUICultures
- Resource Files
- RootNamespace Behaviour
- Culture fallback behaviour
- Configure Middleware
- RequestCultureProviders
- A CustomProvider using CustomRequestCultureProvider
- A CustomProvider using RequestCultureProvider
- Change the Call Order of CultureProvider
- Set the Culture Programmatically
- What is a PO file?
- Configuring PO for AspNetCore
- Change PO file location
- Localization Resources
- References
Terms
-
Globalization - The process of making an app support different languages and regions.
-
Localization - The process of customizing a globalized app for specific languages and regions.
-
Internationalization(I18N) - Both globalization and localization.
-
Culture - A language and, optionally, a region.
-
Neutral Culture - A culture that has a specified language, but not a region (for example "en", "es").
-
Specific Culture - A culture that has a specified language and region (for example, "en-US", "en-GB", "es-CL").
-
Parent Culture - The neutral culture that contains a specific culture (for example, "en" is the parent culture of "en-US" and "en-GB").
IStringLocalizer
-
An interface with an indexer and an
IEnumerable
for returning localized strings. -
It does not require storing the default language strings in a resource file.
-
Useful when you are early in development and you do not need to create resource files.
IHtmlLocalizer
-
Useful for resources that contain HTML.
-
It HTML-encodes arguments that are formatted in the resource string,
IStringLocalizerFactory
-
At the lowest level,
IStringLocalizerFactory
can be retrieved from the DI framework.
Shared Resources
-
You can partition your localized strings by controller or area, or have just one container.
IViewLocalizer
-
It provides localized strings for a view.
-
It finds the resource location from the view file path.
-
It finds the resource file based on the view’s file name.
-
No option to use a global shared resource file.
-
It implements the localizer using
IHtmlLocalizer
. It does not html-encode the localized string. -
It html encodes the parameters and not the resource string itself.
-
To use a shared resource file in a view, inject
IHtmlLocalizer<T>
.
DataAnnotations Localization
-
DataAnnotations error messages are localized with
IStringLocalizer<T>
. -
You can store the error messages in a
ResourcesPath
as shown in the code sample. -
A shared resource can also be used for DataAnnotations error message.
services.AddMvc() .AddDataAnnotationsLocalization(options => { options.DataAnnotationLocalizerProvider = (type, factory) => factory.Create(typeof(SharedResource)); });
With the above code, DataAnnotations only uses the
SharedResource
class for error messages rather than the resource for each class. -
A
SharedResource
is the class corresponding to the.resx
file where the validation messages are stored.
Configuring Localization Services
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources"); (1)
builder.Services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix) (2)
.AddDataAnnotationsLocalization(); (3)
1 | Adds the localization services to the services container, including implementations of IStringLocalizer<T> and IStringLocalizerFactory . |
2 | Support for localized view files. In this sample, view localization is based on the view suffix file. Eg- Index.fr.cshtml . |
3 | Adds support for localized DataAnnotations validation messages through IStringLocalizer abstractions. |
SupportedCultures and SupportedUICultures
-
AspNetCore has two collections of culture values - SupportedCultures and SupportedUICultures.
-
SupportedCultures
-
Determines the results of culture-dependent functions - date, time, number and currency formatting.
-
Determines the sorting order of text, casing-conventions, and string comparisons.
-
-
SuoportedUICultures
-
Determines which translated strings(from .resx files) are looked up by the
ResourceManager
. -
The
ResourceManager
uses theCurrentUICulture
object to lookup culture-specific string.
-
-
-
Every thread in .NET has
CurrentCulture
andCurrentUICulture
objects.
Resource Files
-
A resource file helps separate localizable strings from code.
-
Non-default language strings are isolated in
.resx
resource files. -
Welcome.es.resx
is the file containing translated strings for Spanish.
RootNamespace Behaviour
-
If the root namespace of an assembly is different than the assembly name.
-
Localization does not work by default.
-
It fails because of the way resource files are searched for within the assembly.
-
-
If the
RootNamespace
is different from theAssemblyName
, include the following inAssembly.cs
using System.Reflection; using Microsoft.Extensions.Localization; [assembly: ResourceLocation("Resource Folder Name")] [assembly: RootNamespace("App Root Namespace")]
Culture fallback behaviour
-
This means that if a request comes in for
es-gb
and the site does not have a resource file fores-gb
, it fallsback to the parent culture which ises
and serves the request.
Configure Middleware
-
The localization middleware must be configured before any middleware that might check the request culture. For example,
app.UseMvcWithDefaultRoute()
.builder.Services.Configure<RequestLocalizationOptions>(options => { var supportedCultures = new[] { "en-US", "fr" }; options.SetDefaultCulture(supportedCultures[0]) .AddSupportedCultures(supportedCultures) .AddSupportedUICultures(supportedCultures); });
-
UseRequestLocalization
intializes aRequestLocalizationOptions
object. -
On every request, a list of
RequestCultureProviders
in theRequestLocalizationOptions
is checked to determine the culture to be used by the request.
RequestCultureProviders
-
QueryStringRequestCultureProvider`
-
Some apps use a query string to set the
CultureInfo
. -
It is the first localization provider checked.
-
Pass the query string parameters
culture
andui-culture
. -
If only one value is passed, both
Culture
andUICulture
use that same value.
-
-
CookieRequestCultureProvider
-
Some apps set the culture with the aspnetcore culture cookie.
-
The default cookie name is
.AspNetCore.Culture
. -
The cookie format is
c=en-UK|uic=en-US
.
-
-
AcceptLanguageHeaderRequestCultureProvider
-
This setting indicates what the browser has been set to send or has inherited from the OS.
-
A production app should include a way for a user to customize their choice of culture.
-
A CustomProvider using CustomRequestCultureProvider
-
Suppose you want to let your customers store their language and culture in your databases.
-
You could write a provider to look up these values for the user.
-
Use
RequestLocalizationOptions
to add or remove localization providers.private const string enUSCulture = "en-US"; services.Configure<RequestLocalizationOptions>(options => { var supportedCultures = new[] { new CultureInfo(enUSCulture), new CultureInfo("fr") }; options.DefaultRequestCulture = new RequestCulture(culture: enUSCulture, uiCulture: enUSCulture); options.SupportedCultures = supportedCultures; options.SupportedUICultures = supportedCultures; options.AddInitialRequestCultureProvider(new CustomRequestCultureProvider(async context => { // Custom request culture logic return await Task.FromResult(new ProviderCultureResult("en")); })); });
A CustomProvider using RequestCultureProvider
-
A new implementation of
RequestCultureProvider
can be created to determine the request culture information from a custom source.
Change the Call Order of CultureProvider
-
RequestLocalizationOptions
has three default request culture providers and they are called in the following order:-
QueryStringRequestCultureProvider
-
CookieRequestCultureProvider
-
AcceptLanguageHeaderRequestCultureProvider
-
-
The following code helps change the order.
CookieRequestCultureProvider
is moved to the top andQueryStringRequestCultureProvider
is moved to second spot.app.UseRequestLocalization(options => { var questStringCultureProvider = options.RequestCultureProviders[0]; options.RequestCultureProviders.RemoveAt(0); options.RequestCultureProviders.Insert(1, questStringCultureProvider); });
-
A custom provider via
AddInitialRequestCultureProvider
moves to the top, by default.
Set the Culture Programmatically
-
Setting the culture cookie.
[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); }
What is a PO file?
-
PO files are distributed as text files containing the translated strings for a given language.
-
Benefits of using PO instead of resx:
-
Support pluralization, resx do not support pluralization
-
Not compiled like resx. So no special tooling or build step required.
-
Work well with collaborative online editing tools.
-
#: Pages/Index.cshtml:13 msgid "Hello world!" msgstr "Bonjour le monde!" msgid "There is one item." msgid_plural "There are {0} items." msgstr[0] "Il y a un élément." msgstr[1] "Il y a {0} éléments."
-
#
is a comment indicating the context of the string to be translated. -
msgid
- The untranslated string. -
msgstr
- The transalated string. -
msgid_plural
- The untranslated plural string. -
msgstr[0]
- The translated string for the case 0. -
msgstr[1]
- The translated string for the case N.
Configuring PO for AspNetCore
-
Reference the package:
<PackageReference Include="OrchardCore.Localization.Core" Version="1.5.0" />
-
Register the service:
builder.Services .AddRazorPages() .AddViewLocalization();
-
Create the po file with
<culture code>.po
in the application root folder.msgid "Hello world!" msgstr "Bonjour le monde!"
-
Add razor page
@inject IViewLocalizer Localizer <p>@Localizer["Hello world!"]</p>
Change PO file location
-
PO files are loaded from the Localization folder.
services.AddPortableObjectLocalization(options => options.ResourcesPath = "Localization");
Localization Resources
-
AspNetCore provides
ResourceManagerStringLocalizer
. -
ResourceManagerStringLocalizer
is an implementation ofIStringLocalizer
that usesresx
to store localization resources. -
By implementing,
IStringLocalizer
any data source can be used. -
The following example projects implement
IStringLocalizer
:-