IStringLocalizer
and IStringLocalizer<T>
were architected to improve productivity when developing localized apps. IStringLocalizer
uses the ResourceManager and ResourceReader to provide culture-specific resources at run time. The simple interface has an indexer and an IEnumerable
for returning localized strings. IStringLocalizer
doesn't require you to store 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 code below shows how to wrap the string 'About Title' for localization.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 your 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 will prefer the traditional work flow as it can make it easier to work with longer string literals and make it easier to update localized strings.IHtmlLocalizer<T>
implementation for resources that contain HTML. IHtmlLocalizer
HTML encodes arguments that are formatted in the resource string, but doesn't HTML encode the resource string itself. In the sample highlighted below, only the value of name
parameter is HTML encoded.IStringLocalizerFactory
out of Dependency Injection:SharedResource
is used for shared resources.Startup
class to contain global or shared strings. In the sample below, the InfoController
and the SharedResource
localizers are used: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
: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
will HTML encode the parameters, but not the resource string. Consider the following Razor markup:Key | Value |
---|---|
<i>Hello</i> <b>{0}!</b> | <i>Bonjour</i> <b>{0} !</b> |
IHtmlLocalizer<T>
:IStringLocalizer<T>
. Using the option ResourcesPath = 'Resources'
, the error messages in RegisterViewModel
can be stored in either of the following paths:SharedResource
is the class corresponding to the resx where your validation messages are stored. With this approach, DataAnnotations will only use SharedResource
, rather than the resource for each class.SupportedCultures
and SupportedUICultures
. The CultureInfo object for SupportedCultures
determines the results of culture-dependent functions, such as date, time, number, and currency formatting. SupportedCultures
also determines the sorting order of text, casing conventions, and string comparisons. See CultureInfo.CurrentCulture for more info on how the server gets the Culture. The SupportedUICultures
determines which translates strings (from .resx files) are looked up by the ResourceManager. The ResourceManager
simply looks up culture-specific strings that's determined by CurrentUICulture
. Every thread in .NET hasCurrentCulture
and CurrentUICulture
objects. ASP.NET Core inspects these values when rendering culture-dependent functions. For example, if the current thread's culture is set to 'en-US' (English, United States), DateTime.Now.ToLongDateString()
displays 'Thursday, February 18, 2016', but if CurrentCulture
is set to 'es-ES' (Spanish, Spain) the output will be 'jueves, 18 de febrero de 2016'.LocalizationWebsite.Web.dll
for the class LocalizationWebsite.Web.Startup
would be named Startup.fr.resx. A resource for the class LocalizationWebsite.Web.Controllers.HomeController
would be named Controllers.HomeController.fr.resx. If your targeted class's namespace isn't the same as the assembly name you will need the full type name. For example, in the sample project a resource for the type ExtraNamespace.Tools
would be named ExtraNamespace.Tools.fr.resx.ConfigureServices
method sets the ResourcesPath
to 'Resources', so the project relative path for the home controller's French resource file is Resources/Controllers.HomeController.fr.resx. Alternatively, you can use folders to organize resource files. For the home controller, the path would be Resources/Controllers/HomeController.fr.resx. If you don't use the ResourcesPath
option, the .resx file would go in the project base directory. The resource file for HomeController
would be named Controllers.HomeController.fr.resx. The choice of using the dot or path naming convention depends on how you want to organize your resource files.Resource name | Dot or path naming |
---|---|
Resources/Controllers.HomeController.fr.resx | Dot |
Resources/Controllers/HomeController.fr.resx | Path |
@inject IViewLocalizer
in Razor views follow a similar pattern. The resource file for a view can be named using either dot naming or path naming. Razor view resource files mimic the path of their associated view file. Assuming we set the ResourcesPath
to 'Resources', the French resource file associated with the Views/Home/About.cshtml view could be either of the following:ResourcesPath
option, the .resx file for a view would be located in the same folder as the view.my-project-name.csproj
will use the root namespace my_project_name
and the assembly name my-project-name
leading to this error.RootNamespace
is a build-time value which is not available to the executing process.RootNamespace
is different from the AssemblyName
, include the following in AssemblyInfo.cs (with parameter values replaced with the actual values):NeutralResourcesLanguage
is 'fr-CA')Startup.ConfigureServices
method:AddLocalization
Adds the localization services to the services container. The code above also sets the resources path to 'Resources'.AddViewLocalization
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.AddDataAnnotationsLocalization
Adds support for localized DataAnnotations
validation messages through IStringLocalizer
abstractions.Startup.Configure
method. The localization middleware must be configured before any middleware which might check the request culture (for example, app.UseMvcWithDefaultRoute()
).UseRequestLocalization
initializes a RequestLocalizationOptions
object. On every request the list of RequestCultureProvider
in the RequestLocalizationOptions
is enumerated and the first provider that can successfully determine the request culture is used. The default providers come from the RequestLocalizationOptions
class:QueryStringRequestCultureProvider
CookieRequestCultureProvider
AcceptLanguageHeaderRequestCultureProvider
DefaultRequestCulture
is used.QueryStringRequestCultureProvider
is registered as the first localization provider in the RequestCultureProvider
list. You pass the query string parameters culture
and ui-culture
. The following example sets the specific culture (language and region) to Spanish/Mexico:http://localhost:5000/?culture=es-MX&ui-culture=es-MX
culture
or ui-culture
), the query string provider will set both values using the one you passed in. For example, setting just the culture will set both the Culture
and the UICulture
:http://localhost:5000/?culture=es-MX
MakeCookieValue
method to create a cookie.CookieRequestCultureProvider
DefaultCookieName
returns the default cookie name used to track the user's preferred culture information. The default cookie name is .AspNetCore.Culture
.c=%LANGCODE%|uic=%LANGCODE%
, where c
is Culture
and uic
is UICulture
, for example:Content-Language
header can be added by setting the property ApplyCurrentCultureToResponseHeaders
.Content-Language
header:Content-Language
header with the CurrentUICulture
.Content-Language
explicitly.RequestLocalizationOptions
to add or remove localization providers.Culture
. The Views/Shared/_SelectLanguagePartial.cshtml file allows you to select the culture from the list of supported cultures:footer
section of the layout file so it will be available to all views:SetLanguage
method sets the culture cookie.RequestLocalizationOptions
to a Razor partial through the Dependency Injection container.<languagecode2>-<country/regioncode2>
, where <languagecode2>
is the language code and <country/regioncode2>
is the subculture code. For example, es-CL
for Spanish (Chile), en-US
for English (United States), and en-AU
for English (Australia). RFC 4646 is a combination of an ISO 639 two-letter lowercase culture code associated with a language and an ISO 3166 two-letter uppercase subculture code associated with a country or region. See Language Culture Name.LogLevel.Warning
per request if the requested culture is unsupported. Logging one LogLevel.Warning
per request is can make large log files with redundant information. This behavior has been changed in ASP.NET 3.0. The RequestLocalizationMiddleware
writes a log of type LogLevel.Debug
, which reduces the size of production logs.