Razor的本地化景观

时间:2010-11-22 12:52:50

标签: asp.net-mvc localization razor

我试图诙谐,并使用VirtualPathProvider查找本地化视图。它接受请求的视图路径并在检查文件后修改它。如果找到,则返回本地化的虚拟文件:

public pseudoclass MyFileProvider : VirtualPathProvider
{

    bool FileExists(string requestedPath)
    {
        if (IsLocalizedView(requestedPath))
          return true;
       return base.FileExists(requestedPath);
    }

    bool IsLocalizedView(string requestedPath)
    {
        var uri = requestedUri.AddLocaleByMagic("sv");
        if (FileExistsInternal(uri))
          return true;
    }

    //some more stuff to return the actual file
}

问题是我得到以下异常:

  

VirtualPathProvider返回一个VirtualFile对象,其VirtualPath设置为'/Views/Shared/_Layout.sv.cshtml'而不是预期的'/Views/Shared/_Layout.cshtml'。

当然,我可以伪造文件路径,但这会产生缓存和不同本地化的问题。正确?

任何人都有更好的方法来创建本地化的视图?我不想使用相同的视图,而是使用资源字符串。这样的观点非常可怕,几乎让我哭泣,因为它们很难阅读。

如果你还没有理解我在寻找什么:

/Views/User/Details.sv.cshtml

Hejsan @Model.FirstName

Detta är en lite rolig text på svenska.

/Views/User/Details.en.cshtml

Hello @Model.FirstName

This is a test on english.

控制器

public ActionResult Details()
{
  return View(new User()); //should automagically use a swedish or english view
}

我希望能够在每次请求时手动切换视图(使用CurrentCulture进行本地化)。

3 个答案:

答案 0 :(得分:5)

这是我的实施。它可以更通用,但它满足我的所有要求。

我首先寻找最专业的视图,然后在没有语言规范的情况下尝试。

查看查找过程:

  1. Details.sv-fi.cshtml
  2. Details.sv.cshtml
  3. Details.en.cshtml
  4. Details.cshtml
  5.     public class LocalizedRazorViewEngine : RazorViewEngine
        {
            public LocalizedRazorViewEngine()
            {
                DefaultLanguageCode = "en";
            }
            public string DefaultLanguageCode { get; set; }
    
            public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
            {
                var controllerName = (string)controllerContext.RouteData.Values["controller"];
                var language = GetLanguage(controllerName, viewName);
                if (language != "") language = "." + language;
    
                var masterPath = string.Format("~/Views/Shared/_Layout{0}.cshtml", language);
                var uri = string.Format("~/Views/{0}/{1}{2}.cshtml", controllerName, viewName, language);
                if (VirtualPathProvider.FileExists(uri))
                    return new ViewEngineResult(CreateView(controllerContext, uri, masterPath), this);
    
    
                return base.FindView(controllerContext, viewName, masterName, useCache);
            }
    
            private string GetLanguage(string controllerName, string actionName)
            {
                string format = "~/Views/{0}/{1}.{2}.cshtml";
                if (VirtualPathProvider.FileExists(string.Format(format, controllerName, actionName, Thread.CurrentThread.CurrentCulture.Name)))
                    return Thread.CurrentThread.CurrentCulture.Name;
                if (VirtualPathProvider.FileExists(string.Format(format, controllerName, actionName, Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName)))
                    return Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName;
                if (VirtualPathProvider.FileExists(string.Format(format, controllerName, actionName, DefaultLanguageCode)))
                    return DefaultLanguageCode;
                return string.Empty;
            }
    
    
    
        }
    

    请注意,使用此方法禁用缓存,您可能需要创建自己的缓存(以获取正确的语言)

答案 1 :(得分:2)

您可以编写一个自定义ViewEngine,它根据CurrentCulture返回视图。 一个很好的例子可以在Scott Hanselman's blog post找到,如果移动设备提出请求,它会返回移动视图

答案 2 :(得分:1)

这是最简单的(我猜)使用以下约定在视图之间切换的示例:

  1. MyView.cshtml - 默认一个
  2. MyView.pl.cshtml - 波兰语区域设置
  3. ..等等

        public class LocalizedRazor : RazorViewEngine
        {
        public LocalizedRazor()
            : base()
        {
        }
    
        public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
        {
            var controllerName = (string)controllerContext.RouteData.Values["controller"];
            var format = "~/Views/{0}/{1}.{2}.cshtml";
            var lang = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName;
            if (VirtualPathProvider.FileExists(string.Format(format, controllerName, viewName, lang)))
                return base.FindView(controllerContext, viewName + "." + lang, masterName, useCache);
    
            return base.FindView(controllerContext, viewName, masterName, useCache);
        }
        }
    

    并在Global.asax中:

       protected void Application_Start()
        {
            ViewEngines.Engines.Clear();
            ViewEngines.Engines.Add(new LocalizedRazor());
        }