Domanda

stavo cercando di essere spiritoso e utilizzare un VirtualPathProvider per trovare viste localizzate. Prende il percorso vista richiesta e lo modifica durante il controllo dopo il file. Esso restituisce un file virtuale localizzato se trovato:

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
}

Il problema è che ottengo la seguente eccezione:

  

Il VirtualPathProvider restituito un oggetto VirtualFile con VirtualPath insieme a '/Views/Shared/_Layout.sv.cshtml' invece dei previsti '/Views/Shared/_Layout.cshtml'.

Certo, avrei potuto finto il percorso del file, ma che produrrebbe problemi con il caching e diverse localizzazioni. Giusto?

Chiunque ha un modo migliore per essere in grado di creare viste localizzate? Non voglio usare la stessa vista, ma con le stringhe di risorse, invece. Tali opinioni sono così orribili che quasi mi fa piangere perché sono così difficili da leggere.

Se ancora non hai capito quello che sto cercando:

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

Regolatore

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

Voglio essere in grado di passare da una visualizzazione (ad un localizzato uno utilizzando CurrentCulture) senza dover fare nulla manualmente ad ogni richiesta.

È stato utile?

Soluzione

È possibile scrivere un ViewEngine personalizzato che restituisce una vista a seconda del CurrentCulture. Un bel esempio di questo può essere trovato alla post sul blog di Scott Hanselman, che fa tornare mobili Visualizzazioni se la richiesta è stata fatta da un dispositivo mobile

Altri suggerimenti

Ecco la mia implementazione. Si potrebbe essere reso più generico, ma soddisfa tutte le mie esigenze.

I cerca la vista più specializzata prima e cerca senza un ultima lingua specfication.

Visualizza processo di ricerca:

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



    }

Si noti che la memorizzazione nella cache è disabilitato utilizzando questo approccio e potrebbe essere necessario per creare il proprio cache (per ottenere la lingua corretta)

Questa è la più semplice come può essere (credo) esempio di passare da una vista utilizzando la seguente convenzione:

  1. MyView.cshtml - di default
  2. MyView.pl.cshtml - locale polacca

.. e così via

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

e in Global.asax:

   protected void Application_Start()
    {
        ViewEngines.Engines.Clear();
        ViewEngines.Engines.Add(new LocalizedRazor());
    }
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top