Yeldar Kurmangaliyev
Yeldar Kurmangaliyev

Reputation: 34189

How to localize structures HTML views in ASP.NET?

I have a multi-language website and views content (including the markup) can differ from language to language. That's why I cannot just localize strings and put them into resources.

For example, my view in Russian:

<div class="card">
    <div class="card-image">
        <img src="~/Images/CardHeaders/Business_CreditsSME.jpg" />
    </div>
    <div class="card-content">
        Text
    </div>            
</div>

View in English:

<p>Text</p>

I see two ways to localize this:

  1. Create Page.cshtml and Page.en.cshtml, and create a custom LocaleView() method in controller which will use the localized view files.

    • The problem is that Views do not always differ. It means that sometimes I will duplicate the markup.
  2. Copy all the HTML markup in my resources as it is, and use Html.Raw(Resources.PageView).

    • It is not convenient to create, modify or read HTML which is located in a resource flies
    • Moreover, I do not like Html.Raw method at all and prefer not to use it anywhere

How do you localize large views of different structures?

Upvotes: 0

Views: 1337

Answers (2)

Yeldar Kurmangaliyev
Yeldar Kurmangaliyev

Reputation: 34189

I have combined two solutions.

  1. I have overriden View method in my base controller so that it looks for the existent localized view. Now, if my views differ too much, I simply create View.en.cshtml file and it is automatically being processed by a controller:

    public abstract class BaseController : Controller
    {
        protected override ViewResult View(string viewName, string masterName, object model)
        {
            if (string.IsNullOrEmpty(viewName)) 
                viewName = (string)RouteData.Values["action"];
    
            string localizedViewName = $"{viewName}.{CultureInfo.CurrentCulture.Name}";
            bool hasLocalizedView = ViewEngines.Engines
                .FindPartialView(ControllerContext, localizedViewName)
                .View != null;
    
            return base.View(hasLocalizedView ? localizedViewName : viewName, masterName, model);
        }
    }
    
  2. If my views have the same structure, then I don't create separate files, but simply use the same view with localized strings within it like this:

    <div class="card">
        <div class="card-image">
            <img src="~/Images/CardHeaders/Business_CreditsSME.jpg" />
        </div>
        <div class="card-content">
            @GlobalResources.LocalizedText
        </div>            
    </div>
    

The structure now looks like:

- Views
-- About
--- History.cshtml
--- History.kk.cshtml
--- History.en.cshtml
--- Vacancies.cshtml

where Vacancies.cshtml file uses resources to localize a page, and History* files are localized like a plain text without resources.

Upvotes: 1

Lair Jr
Lair Jr

Reputation: 64

Awesome question!

Between these two option the first one look a little bit better.

But one thing that I usually do. It's created an HTML helper to locate the localised view.

So, you will be able to use it on the view like this:

@Html.RenderLocale("YourView", ...);

Then, in your RenderLocale, you change the file path to the view that the user wants.

public static string RenderLocale(this HtmlHelper helper, string target, ...)
{
     var filePath = this.getLocaleFilePath(target); //it returns yourView.cshtml or yourView.ru.cshtml
     return this.Action(filePath); // it renders or performs the action you want     
}

Upvotes: 0

Related Questions