Pregunta

Yo estaba tratando de ser ingenioso y utilizar un VirtualPathProvider para encontrar puntos de vista localizadas. Se toma el camino y lo modifica cuando la comprobación después del archivo vista solicitada. Se devuelve un archivo virtual localizada si se encuentra:

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
}

El problema es que tengo la siguiente excepción:

  

El VirtualPathProvider devuelve un objeto VirtualFile con el conjunto VirtualPath a '/Views/Shared/_Layout.sv.cshtml' en lugar del esperado '/Views/Shared/_Layout.cshtml'.

Claro, yo podría falsificar la ruta del archivo, sino que produciría problemas con el almacenamiento en caché y diferentes localizaciones. ¿Verdad?

Alguien tiene una mejor manera de poder crear vistas localizados? No quiero usar la misma vista pero con cadenas de recursos en su lugar. Estos puntos de vista son tan horrible que casi me hace llorar porque son tan difíciles de leer.

Si todavía no has entendido lo que estoy buscando:

/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.

controlador

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

Quiero ser capaz de cambiar de vista (a una localizada usando uno CurrentCulture) sin tener que hacer nada manualmente en cada solicitud.

¿Fue útil?

Solución

Se puede escribir una ViewEngine a medida que devuelve puntos de vista dependiendo de la CurrentCulture. Un buen ejemplo de esto se puede encontrar en de Scott Hanselman entrada de blog , que hace regresar móviles Vistas si la solicitud ha sido hecha por un dispositivo móvil

Otros consejos

Aquí está mi aplicación. Podría ser más genérico, pero que cumple todas mis necesidades.

Me parece a la vista más especializada primera y trata sin una última lengua specfication.

Vista proceso de búsqueda:

  1. Details.sv-fi.cshtml
  2. Details.sv.cshtml
  3. Details.en.cshtml
  4. Details.cshtml

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



    }

Tenga en cuenta que el almacenamiento en caché está deshabilitado usando este método y puede que necesite para crear su propia caché (para obtener el idioma correcto)

Aquí es el más simple como puede ser (supongo) ejemplo de conmutación entre las vistas usando la siguiente convención:

  1. MyView.cshtml - por defecto
  2. MyView.pl.cshtml - localidad polaca

.. y así sucesivamente

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

y en Global.asax:

   protected void Application_Start()
    {
        ViewEngines.Engines.Clear();
        ViewEngines.Engines.Add(new LocalizedRazor());
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top