Search code examples
asp.net-mvc-5resx

Creating A Per-View Resource File In MVC


I am converting a localized WebForms application to MVC5. Most of the examples I have seen for MVC have a single resource - resx - file (per language) for the entire application.

Is it possible, to have a separate file for each view? If so, is there an example of how to reference the said file?

UPDATE: I would like to leave the resource files uncompiled if possible. This would allow us to edit the RESX files on the fly without having to recompile the site everytime.

Below is the procedure I had in WebForms. I am essentially trying to reproduce this in MVC5.

public string LocalizeText(Page CurrentPage, string resourceKey)
    {
        string localizedText = string.Empty;

        // LOOK FOR LOCALIZED TEXT
        String filePath = string.Empty;
        if (!String.IsNullOrEmpty(CurrentPage.Request.GetFriendlyUrlFileVirtualPath()))
        {
            filePath = CurrentPage.Request.GetFriendlyUrlFileVirtualPath();   // FOR FRIENDLY URLS
        }
        else
        {
           filePath = CurrentPage.Request.CurrentExecutionFilePath; // FOR "UNFRIENDLY" URLS (THOSE WITH A FILE EXTENSION VISIBLE)
        }

        try
        {
            localizedText = Convert.ToString(HttpContext.GetLocalResourceObject(filePath, resourceKey, System.Globalization.CultureInfo.CurrentCulture)).Trim();
        }
        catch (Exception ex)
        {
             HttpContext.Current.Response.Write(ex.ToString() + "<br />" + filePath);
        }


        return localizedText;

    }

The resource files would be located in the App_LocalResources folder.


Solution

  • Yes, it is possible to have a separate resource file for a view. As a really simple, and pretty dull example (sorry about that :-)), consider the following view model:

    using _31662592.Resources;
    using System.ComponentModel.DataAnnotations;
    
    public class HomeViewModel
    {
        [Display(Name = "WelcomeHeader", ResourceType = typeof(HomeResources))]
        public string WelcomeHeader { get; set; }
        [Display(Name = "WelcomeMessage", ResourceType = typeof(HomeResources))]
        public string WelcomeMessage { get; set; }
    }
    

    Here, I'm making use of the Display attribute, which has support for localisation. So in my case, the resource file I created looks like this:

    Resources File

    As you can see, the ResourceType property corresponds with the type of your resource file (i.e. HomeResources in my case), and the Name property corresponds with the name of the string in the resource file which you wish to bind the property to.

    Nothing fancy in the action:

    public ActionResult Index()
    {
        return View(new HomeViewModel());
    }
    

    The view is very simple too:

    @model _31662592.Models.HomeViewModel
    
    <h1>@Html.DisplayNameFor(m => m.WelcomeHeader)</h1>
    
    <p>@Html.DisplayNameFor(m => m.WelcomeMessage)</p>
    

    You can even use the resources inline in your views, such as:

    @using _31662592.Resources
    
    <h1>@HomeResources.WelcomeHeader</h1>
    
    <p>@HomeResources.WelcomeMessage</p>
    

    In case you have any problems, you should make sure that:

    1. The Build Action for the resource is set to "Embedded Resource".
    2. The Custom Tool for the resource is set to "PublicResXFileCodeGenerator".

    Both of these options can be set by right-clicking on the resource file and selecting Properties. Those options will then be shown in the properties dockable window. Finally, if you wish to reference the resource file from another project, make sure it's set to Public rather than internal, which you can set by double-clicking the resource file to open it as normal, then changing its access modifier from internal to public.