Reputation: 14155
I'm using LocalizationAttribute
which implements ActionFilterAttribute
to localize views. I simply put [Localize]
on controller. I was using LocalizeStrings.resx files to apply based on which language is on current thread. Everything works for this simple case (with localized strings). Now I want to localize complete pages (not just strings).
To acomplish this which approach do you use?
Do I need to identify which thread is current on controller and based on that value to call view:
public ActionResult AboutUs()
{
switch (Thread.CurrentThread.CurrentUICulture.Name)
{
case "en-US":
return View("EnglishUSView");
case "de-DE":
return View("GermanView");
default:
return View();
}
return View();
}
or do you recommend something else ?
Upvotes: 4
Views: 2162
Reputation: 17064
I believe there are numerous ways to achieve this but you can follow this one below.
Firstly you can assume some naming convention for the views, by adding culture suffix to their names i.e. ViewName_en-US.cshtml, ViewName_pl-PL.cshtml, etc.
If so, don't construct these names in each action separately based on the current culture. Just write common logic which takes care of that - base controller with overriden OnActionExecuted
method:
public class BaseController : Controller
{
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext);
var view = filterContext.Result as ViewResultBase;
if(view != null)
{
var viewName = string.IsNullOrEmpty(view.ViewName)
? filterContext.RouteData.Values["action"].ToString()
: view.ViewName; // retrieve the custom view name if provided or default action name otherwise
var cultureName = Thread.CurrentThread.CurrentUICulture.Name;
var localizedViewName = string.Format("{0}_{1}", viewName, cultureName); // construct composite, culture-aware name
if (ViewExists(localizedViewName)) // safety check in case not all your views are localized - if so, just return the default name
{
filterContext.Result = new ViewResult { ViewName = localizedViewName };
}
}
}
private bool ViewExists(string name)
{
var result = ViewEngines.Engines.FindView(ControllerContext, name, null);
return result.View != null;
}
}
Actions don't require any localization handling right now:
public class HomeController : BaseController
{
public ActionResult AboutUs()
{
// (...) nothing special here
return View();
}
}
Upvotes: 2
Reputation: 3467
I would recommend to simply extended RazorViewEngine
and override FindPartialView
and FindView
in order to inform ViewEngine to look is there view with current culture inside thread. If that page cannot be found than proceed as usuall.
RazorViewEngine
Index.cshtml
and Index.de-DE.cshtml
Global.asax.cs
file, inside application start you should call localized view engine (the one which implements RazorViewEngine)Controller
no further modification needed
Views
/Views/Home/Index.cshtml
/Views/Home/Index.de.DE.cshtml
Helper
public class LocalizedRazorViewEngine : RazorViewEngine
{
public override ViewEngineResult FindPartialView ...
public override ViewEngineResult FindView...
}
ApplicationStart
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new LocalizedRazorViewEngine());
Upvotes: 7
Reputation: 15901
You would usually implement the rule in a Viewengine. Its easier than it sounds.
http://biasecurities.com/2010/01/localized-asp-net-mvc-views-using-a-localizedviewengine/
Upvotes: 1