Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC 6 : how to use RESX files?

I am trying to migrate my existing ASP.NET MVC 5 project to MVC 6 vNext project , while I have been able to get through and resolve most of the issues , I cant seem to find any documentation on how to use the RESX resource files for localization in MVC 6

My ViewModels are using statements like

 [Required(ErrorMessageResourceType = typeof(Resources.MyProj.Messages), ErrorMessageResourceName = "FieldRequired")]

This worked fine in MVC 5 as long as the RESX was included properly and the access modifiers were set correctly , but it doesnt seem to work in a vNext project Does anyone know how RESX can be used in MVC 6 vNext projects ?

I saw a few posts here and on the GIT hub site which say that the localization story for ASP.NET 5 / MVC 6 is complete but I cant find any decent sample where the resource strings have been used.

Using the code above gives me a error

Error CS0246 The type or namespace name 'Resources' could not be found (are you missing a using directive or an assembly reference?)

Edit : Changed text to clarify that I am looking for implementation of localization in vNext ( MVC 6 )projects , I am able to make it work in MVC 5.

Edit 2 : Got the localization bit working after implementing the answer from Mohammed but I am stuck at a new error now.

Once I Include

  "Microsoft.AspNet.Localization": "1.0.0-beta7-10364",
    "Microsoft.Framework.Localization": "1.0.0-beta7-10364",

packages and add the following line in ConfigureServices in the Startup.cs

   services.AddMvcLocalization();

I get a new error when the following code is getting executed.

  public class HomeController : Controller
    {
        private readonly IHtmlLocalizer _localizer;

        public HomeController(IHtmlLocalizer<HomeController> localizer)
        {
            _localizer = localizer;
        }
          ....

Error :

An unhandled exception occurred while processing the request.

InvalidOperationException: Unable to resolve service for type 'Microsoft.Framework.Runtime.IApplicationEnvironment' while attempting to activate 'Microsoft.Framework.Localization.ResourceManagerStringLocalizerFactory'. Microsoft.Framework.DependencyInjection.ServiceLookup.Service.CreateCallSite(ServiceProvider provider, ISet`1 callSiteChain)

Cant figure out if its a dependency i am missing or there is a issue in the code

Edit 3 :

To anyone still looking for a solution. At this point in time , you can use the code in the answer by Muhammad Rehan Saee to get localization support in your CSHTML. However the story for enabling localization in validation attributes is not yet done( at the time of this edit : 08/Sep/2015) Have a look at the issue on the GITHUB site for mvc below :

https://github.com/aspnet/Mvc/issues/2766#issuecomment-137192942

PS : To fix the InvalidOperationException I did the following

Taking all dependencies as the beta7-* and clearing all the contents of my C:\Users\.dnx\packages got rid of the error.

Details on the issue I raised :

https://github.com/aspnet/Mvc/issues/2893#issuecomment-127164729

Edit : 25 / Dec /2015

This is finally working in MVC 6 now.

Wrote a quick blog post here : http://pratikvasani.github.io/archive/2015/12/25/MVC-6-localization-how-to/

like image 625
Pratik Avatar asked Jul 30 '15 10:07

Pratik


People also ask

How do I read a RESX file?

Create an App_GlobalResources system folder and add a resource file to it e.g. Messages. resx. Create your entries in the resource file e.g. ErrorMsg = This is an error. Then to access that entry: string errormsg = Resources.

How do I search in RESX files?

Just open any resx file and press ctrl+f, then search for some data inside existing row there.


1 Answers

You can take a look at a full sample on the ASP.NET MVC GitHub project here. At the time of writing this is all very new code and subject to change. You need to add the following into your startup:

public class Startup
{
    // Set up application services
    public void ConfigureServices(IServiceCollection services)
    {
        // Add MVC services to the services container
        services.AddMvc();
        services.AddMvcLocalization();

        // Adding TestStringLocalizerFactory since ResourceStringLocalizerFactory uses ResourceManager. DNX does
        // not support getting non-enu resources from ResourceManager yet.
        services.AddSingleton<IStringLocalizerFactory, TestStringLocalizerFactory>();
    }

    public void Configure(IApplicationBuilder app)
    {
        app.UseCultureReplacer();

        app.UseRequestLocalization();

        // Add MVC to the request pipeline
        app.UseMvcWithDefaultRoute();
    }
}

The IStringLocalizerFactory seems to be used to create instances of IStringLocalizer from resx types. You can then use the IStringLocalizer to get your localized strings. Here is the full interface (LocalizedString is just a name value pair):

/// <summary>
/// Represents a service that provides localized strings.
/// </summary>
public interface IStringLocalizer
{
    /// <summary>
    /// Gets the string resource with the given name.
    /// </summary>
    /// <param name="name">The name of the string resource.</param>
    /// <returns>The string resource as a <see cref="LocalizedString"/>.</returns>
    LocalizedString this[string name] { get; }

    /// <summary>
    /// Gets the string resource with the given name and formatted with the supplied arguments.
    /// </summary>
    /// <param name="name">The name of the string resource.</param>
    /// <param name="arguments">The values to format the string with.</param>
    /// <returns>The formatted string resource as a <see cref="LocalizedString"/>.</returns>
    LocalizedString this[string name, params object[] arguments] { get; }

    /// <summary>
    /// Gets all string resources.
    /// </summary>
    /// <param name="includeAncestorCultures">
    /// A <see cref="System.Boolean"/> indicating whether to include
    /// strings from ancestor cultures.
    /// </param>
    /// <returns>The strings.</returns>
    IEnumerable<LocalizedString> GetAllStrings(bool includeAncestorCultures);

    /// <summary>
    /// Creates a new <see cref="ResourceManagerStringLocalizer"/> for a specific <see cref="CultureInfo"/>.
    /// </summary>
    /// <param name="culture">The <see cref="CultureInfo"/> to use.</param>
    /// <returns>A culture-specific <see cref="IStringLocalizer"/>.</returns>
    IStringLocalizer WithCulture(CultureInfo culture);
}

Finally you can inject the IStringLocalizer into your Controller like so (Note that IHtmlLocalizer<HomeController> inherits from IStringLocalizer):

public class HomeController : Controller
{
    private readonly IHtmlLocalizer _localizer;

    public HomeController(IHtmlLocalizer<HomeController> localizer)
    {
        _localizer = localizer;
    }

    public IActionResult Index()
    {
        return View();
    }

    public IActionResult Locpage()
    {
        ViewData["Message"] = _localizer["Learn More"];
        return View();
    }
}
like image 63
Muhammad Rehan Saeed Avatar answered Sep 19 '22 05:09

Muhammad Rehan Saeed