根据当前文化调用不同的(本地化)视图

时间:2013-05-11 18:49:57

标签: c# asp.net-mvc internationalization

我正在使用LocalizationAttribute来实现ActionFilterAttribute来本地化视图。我只是将[Localize]放在控制器上。我正在使用LocalizeStrings.resx文件根据当前线程上的语言进行应用。一切都适用于这个简单的情况(使用本地化的字符串)。现在我想本地化完整的页面(而不仅仅是字符串)。

要使用哪种方法?

我是否需要确定哪个线程在控制器上是最新的并且基于该值来调用视图:

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();
}

或者你推荐别的什么?

3 个答案:

答案 0 :(得分:7)

我建议只是扩展RazorViewEngine并覆盖FindPartialViewFindView,以便通知ViewEngine在线程中查看当前文化的视图。如果找不到该页面,请继续使用。

  1. 延长RazorViewEngine
  2. Inside View文件夹应该是(假设英语是默认语言。)Index.cshtmlIndex.de-DE.cshtml
  3. 修改Global.asax.cs文件,在应用程序启动内你应该调用本地化视图引擎(实现RazorViewEngine的那个)
  4. <强>控制器

    no further modification needed
    

    <强>视图

    /Views/Home/Index.cshtml
    /Views/Home/Index.de.DE.cshtml
    

    <强>辅助

    public class LocalizedRazorViewEngine : RazorViewEngine
    {
       public override ViewEngineResult FindPartialView ...
       public override ViewEngineResult FindView...
    }
    

    <强> ApplicationStart

    ViewEngines.Engines.Clear();
    ViewEngines.Engines.Add(new LocalizedRazorViewEngine());
    

答案 1 :(得分:2)

我相信有很多方法可以实现这一目标,但您可以按照以下方式进行操作。

首先,您可以为视图添加一些命名约定,方法是将文化后缀添加到其名称中,即ViewName_ en-US .cshtml,ViewName_ pl-PL .cshtml,等

如果是这样,请不要根据当前文化在每个操作中单独构造这些名称。只需编写通用逻辑来处理 - 使用覆盖OnActionExecuted方法的基本控制器:

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;
    }
}

现在,操作不需要任何本地化处理:

public class HomeController : BaseController 
{
    public ActionResult AboutUs()
    {            
        // (...) nothing special here
        return View();
    }
}

答案 2 :(得分:1)

您通常会在Viewengine中实施规则。它比听起来容易。

http://biasecurities.com/2010/01/localized-asp-net-mvc-views-using-a-localizedviewengine/