How to get resource strings in strongly typed way in asp.net core?

Vikram Babu Nagineni picture Vikram Babu Nagineni · Feb 1, 2017 · Viewed 8.6k times · Source

In the following program, in order to get resource strings i am using _localizer["About Title"] where "About Title" is a magic string. How to avoid using strings like this? Is there any strongly typed way?

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;

namespace Localization.StarterWeb.Controllers
{
    [Route("api/[controller]")]
    public class AboutController : Controller
    {
        private readonly IStringLocalizer<AboutController> _localizer;

        public AboutController(IStringLocalizer<AboutController> localizer)
        {
            _localizer = localizer;
        }

        [HttpGet]
        public string Get()
        {
            return _localizer["About Title"];
        }
    }
}

Answer

Mariusz Jamro picture Mariusz Jamro · Aug 14, 2018
  1. Create a Resource file (.resx) with your translations. For example if you're localizing AboutController that would be something like AboutController.String.resx.

  2. Enable code generation for your resource file by changing Access Modifier from "No code generation" to "Public" or "Internal" while on edit resource screen. On save this will create a .Designer.cs class for your resource file. It will contain a static property for each key in the resource file. Don't modify the generated class manually. It'll be regenerated automatically after each modification of the .resx.

enter image description here

  1. Use the generated designer class in your controller to get translated text (no need for string localizer in that case):

     [HttpGet]
     public string Get()
     {
         return AboutController_Strings.AboutTitle;
     }
    

    This will work with using static trick as well:

     using static Localization.StarterWeb.AboutController_Strings;
    
     //(...)
    
     [HttpGet]
     public string Get()
     {
         return AboutTitle;
     }
    

    Alternatively you can use it with ASP's localizers. This adds no value at in that particular case but can be useful with the IHtmlLocalizer as it'll html-escape the values for you.

     [HttpGet]
     public string Get()
     {
         return _localizer[nameof(AboutTitle)];
     }
    

Why is this better than the accepted answer? This way you do not need to manually create and maintain all of LocalizationKeys-like classes with number of const strings inside. (In bigger projects there will be hundreds or thousands of them!) The generated .Designer.cs class will contain all keys from your resource file. Nothing more. Nothing less. If you delete something from the resource fill it will be deleted from the generated code and produce compilation errors in your code wherever the deleted property was used. If you add something to the resource file it will automatically generate a new property on save of the resource file which will appear in code-completion.

This is a more traditional approach, the way it was originally done with with for example WinForms. In the Microsoft's documentation for localizing ASP.NET Core apps there a brief explanation why they added a new way using IStringLocalizer: hardcoding translation string makes your workflow faster. There's no need to maintain additional things until needed.

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.