ASP.NET Core Localization – Strings

In my last post on localization I showed how culture determines the formatting of dates and numbers, and how ASP.NET Core determines the culture of a request.  In this post I’ll look at how we provide localized strings using ASP.NET Core.

You can download the example projects here:

Note:  these projects use the RC2 daily builds; to use the dailies, please see this post.

Using Resource Files

ASP.NET Core uses a default string localization implementation based on resource files, which are XML files containing locale specific translations. We have the option to create resource files by type, or to create shared resource files.  For example, in this project I have a resource file per locale for the Startup class, and I also have a set of resource files named “Shared” that I intend to use for all types:

resource-files

To configure string localization, we call the AddLocalization extension method in the Startup.ConfigureServices method:

AddLocalization has an overload that lets us configure a LocalizationOptions instance, which we are using here.  LocalizationOptions has a single property that lets us configure the relative path to the resource files under the application root.

In the Startup.Configure method, we take an instance of IStringLocalizer<Startup>, which gives us access to the strings in the AspNetLocalization03.Startup.* resource files, and an IStringLocalizerFactory instance, which we’ll use to get the shared localized strings:

In the method where we construct the response, we can use the IStringLocalizerFactory to create an IStringLocalizer that uses the shared resource files, or we can use the IStringLocalizer associated with the Startup type:

Note that we don’t define localized versions of the strings "Current Culture" and "Current UI Culture", and the ResourceManagerStringLocalizer returns the requested string names when it can’t find a localized value.

Browsing to the site and passing cultures on the query string, we see the values defined in the resource files.  Note that the current culture determines formatting and the current UI culture determines the locale specific strings used:

aspnet-localization-strings

Using a Custom String Localizer

If ResourceManagerStringLocalizer doesn’t meet your needs (maybe you need to store locale specific strings in a database), you can create your own string localizer by implementing the IStringLocalizer interface:

LocalizedString encapsulates a locale specific string and has properties to access the string value, the name associated with the string, and whether the value was found for the locale.

In the example project, I defined a MyStringLocalizer class that has two constructors, with one allowing the caller to specify a culture for the string localizer:

As you can see, the class also keeps an in-memory list of string data to use as a test data store.  When a caller asks for a localized string, it uses either the culture set in the constructor or the current UI culture.  Using the culture and the name requested, it constructs a LocalizedString using a match from the list data, or the name if no match was found.  You can imagine getting the localized string from a database or cache here instead:

ASP.NET Core also defines an IStringLocalizerFactory interface:

Since we aren’t partitioning the resources according to type or any other attribute, we can implement this class to simply return a new instance of MyStringLocalizer:

Contrast this with the ResourceManagerStringLocalizerFactory, which makes use of the Type passed in to return a StringLocalizer associated with the resources for that type.  

In a real project, you might define options that could be used by the factory, or have the factory keep a cache; you can look at the source code of ResourceManagerStringLocalizerFactory for examples of this.

Finally, we create an extension method to register our implementations with the service collection:

ASP.NET Core defines the StringLocalizer<T> class, and it uses the registered IStringLocalizerFactory implementation internally to get an IStringLocalizer object.

To use our custom IStringLocalizer implementation, we just need to call our extension method, and ask for an IStringLocalizer<T> instance in the Startup.Configure method:

Everything else is substantially the same as in the example using the ResourceManagerStringLocalizer; I changed the list of supported cultures so it is clear we are using the custom StringLocalizer:

aspnet-localization-strings-custom

1 Comment

  1. […] my next post, I’ll look at how ASP.NET Core uses the UI culture to provide localized […]

Leave a Reply