9.3 KiB
title | author | description | ms.author | monikerRange | ms.date | uid |
---|---|---|---|---|---|---|
Make an ASP.NET Core app's content localizable | rick-anderson | Learn how to make an ASP.NET Core app's content localizable to prepare the app for localizing content into different languages and cultures. | riande | >= aspnetcore-5.0 | 02/23/2023 | fundamentals/localization/make-content-localizable |
Make an ASP.NET Core app's content localizable
:::moniker range="> aspnetcore-5.0"
By Hisham Bin Ateya, Damien Bowden, Bart Calixto and Nadeem Afana
One task for localizing an app is to wrap localizable content with code that facilitates replacing that content for different cultures.
IStringLocalizer
xref:Microsoft.Extensions.Localization.IStringLocalizer and xref:Microsoft.Extensions.Localization.IStringLocalizer%601 were architected to improve productivity when developing localized apps. IStringLocalizer
uses the xref:System.Resources.ResourceManager and xref:System.Resources.ResourceReader to provide culture-specific resources at run time. The interface has an indexer and an IEnumerable
for returning localized strings. IStringLocalizer
doesn't require storing the default language strings in a resource file. You can develop an app targeted for localization and not need to create resource files early in development.
The following code example shows how to wrap the string "About Title" for localization.
In the preceding code, the IStringLocalizer<T>
implementation comes from Dependency Injection. If the localized value of "About Title" isn't found, then the indexer key is returned, that is, the string "About Title".
You can leave the default language literal strings in the app and wrap them in the localizer, so that you can focus on developing the app. You develop an app with your default language and prepare it for the localization step without first creating a default resource file.
Alternatively, you can use the traditional approach and provide a key to retrieve the default language string. For many developers, the new workflow of not having a default language .resx file and simply wrapping the string literals can reduce the overhead of localizing an app. Other developers prefer the traditional work flow as it can be easier to work with long string literals and easier to update localized strings.
IHtmlLocalizer
Use the xref:Microsoft.AspNetCore.Mvc.Localization.IHtmlLocalizer%601 implementation for resources that contain HTML. xref:Microsoft.AspNetCore.Mvc.Localization.IHtmlLocalizer HTML-encodes arguments that are formatted in the resource string, but doesn't HTML-encode the resource string itself. In the following highlighted code, only the value of the name
parameter is HTML-encoded.
NOTE: Generally, only localize text, not HTML.
IStringLocalizerFactory
At the lowest level, xref:Microsoft.Extensions.Localization.IStringLocalizerFactory can be retrieved from of Dependency Injection:
The preceding code demonstrates each of the two factory create methods.
Shared resources
You can partition your localized strings by controller or area, or have just one container. In the sample app, a marker class named SharedResource
is used for shared resources. The marker class is never called:
In the following sample, the InfoController
and the SharedResource
localizers are used:
View localization
The xref:Microsoft.AspNetCore.Mvc.Localization.IViewLocalizer service provides localized strings for a view. The ViewLocalizer
class implements this interface and finds the resource location from the view file path. The following code shows how to use the default implementation of IViewLocalizer
:
The default implementation of IViewLocalizer
finds the resource file based on the view's file name. There's no option to use a global shared resource file. ViewLocalizer
implements the localizer using IHtmlLocalizer
, so Razor doesn't HTML-encode the localized string. You can parameterize resource strings, and IViewLocalizer
HTML-encodes the parameters but not the resource string. Consider the following Razor markup:
@Localizer["<i>Hello</i> <b>{0}!</b>", UserManager.GetUserName(User)]
A French resource file could contain the following values:
Key | Value |
---|---|
<i>Hello</i> <b>{0}!</b> |
<i>Bonjour</i> <b>{0} !</b> |
The rendered view would contain the HTML markup from the resource file.
Generally, only localize text, not HTML.
To use a shared resource file in a view, inject IHtmlLocalizer<T>
:
DataAnnotations localization
DataAnnotations error messages are localized with IStringLocalizer<T>
. Using the option ResourcesPath = "Resources"
, the error messages in RegisterViewModel
can be stored in either of the following paths:
- Resources/ViewModels.Account.RegisterViewModel.fr.resx
- Resources/ViewModels/Account/RegisterViewModel.fr.resx
Non-validation attributes are localized.
How to use one resource string for multiple classes
The following code shows how to use one resource string for validation attributes with multiple classes:
services.AddMvc()
.AddDataAnnotationsLocalization(options => {
options.DataAnnotationLocalizerProvider = (type, factory) =>
factory.Create(typeof(SharedResource));
});
In the preceding code, SharedResource
is the class corresponding to the .resx file where the validation messages are stored. With this approach, DataAnnotations only uses SharedResource
, rather than the resource for each class.
Configure localization services
Localization services are configured in Program.cs
:
-
xref:Microsoft.Extensions.DependencyInjection.LocalizationServiceCollectionExtensions.AddLocalization%2A adds the localization services to the services container, including implementations for
IStringLocalizer<T>
andIStringLocalizerFactory
. The preceding code also sets the resources path to "Resources". -
xref:Microsoft.Extensions.DependencyInjection.MvcLocalizationMvcBuilderExtensions.AddViewLocalization%2A adds support for localized view files. In this sample, view localization is based on the view file suffix. For example "fr" in the
Index.fr.cshtml
file. -
xref:Microsoft.Extensions.DependencyInjection.MvcDataAnnotationsMvcBuilderExtensions.AddDataAnnotationsLocalization%2A adds support for localized
DataAnnotations
validation messages throughIStringLocalizer
abstractions.
Next steps
Localizing an app also involves the following tasks:
- Provide localized resources for the languages and cultures the app supports
- Implement a strategy to select the language/culture for each request
Additional resources
- Url culture provider using middleware as filters in ASP.NET Core
- Applying the RouteDataRequest CultureProvider globally with middleware as filters
- xref:fundamentals/localization
- xref:fundamentals/localization/provide-resources
- xref:fundamentals/localization/select-language-culture
- xref:fundamentals/troubleshoot-aspnet-core-localization
- Globalizing and localizing .NET applications
- Localization.StarterWeb project used in the article.
- Resources in .resx Files
- Microsoft Multilingual App Toolkit
- Localization & Generics
:::moniker-end
[!INCLUDE make-content-localizable5]