Frage

Ich habe versucht, witzig zu sein und eine VirtualPathProvider verwenden lokalisierte Ansichten zu finden. Es nimmt die angeforderte Ansicht Pfad und ändert sie, wenn sie nach der Datei zu überprüfen. Es gibt eine lokalisierte virtuelle Datei, falls gefunden:

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
}

Das Problem ist, dass ich die folgende Ausnahme erhalten:

  

Die VirtualPathProvider zurück ein Virtual Objekt mit VirtualPath Satz zu ‚/Views/Shared/_Layout.sv.cshtml‘ statt dem erwarteten ‚/Views/Shared/_Layout.cshtml‘.

Klar, ich könnte Fälschung der Dateipfad, aber das würde Probleme mit Caching und verschiedenen Lokalisierungen produzieren. Richtig?

Jeder bekam einen besseren Weg zu schaffen, um die Lage sein, lokale Ansichten? Ich will nicht die gleiche Ansicht verwenden, aber mit Ressourcen-Strings statt. Solche Ansichten sind so schrecklich, dass sie macht mich fast weinen, weil sie so schwer zu lesen.

Wenn Sie immer noch nicht verstanden, was ich suche:

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

Controller

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

Ich möchte in der Lage sein, Ansichten zu wechseln (auf einer lokalisierten ein Current verwendet wird), ohne etwas zu jeder Anforderung manuell zu tun.

War es hilfreich?

Lösung

Sie können eine benutzerdefinierte Viewengine schreiben, die Ansichten gibt je nach Current. Ein schönes Beispiel hierfür kann unter Scott Hanselman Blog-Post gefunden werden, die mobilen Ansichten zurückkehren wenn Anforderung von einem mobilen Gerät gemacht worden

Andere Tipps

Hier ist meine Implementierung. Es könnte aus allgemeineren, aber es erfüllt alle meine Anforderungen.

ich suche die spezialisierte Ansicht zuerst und versucht ohne Sprache specfication letzte.

Ansicht Findungsprozess:

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



    }

Beachten Sie, dass das Caching deaktiviert ist dieser Ansatz verwendet, und Sie können Ihren eigenen Cache erstellen müssen (die richtige Sprache zu erhalten)

Dies ist die einfachste wie (ich glaube) Beispiel für das Umschalten zwischen Ansichten, die wie folgt definiert:

  1. MyView.cshtml - default ein
  2. MyView.pl.cshtml - Polnisch locale

.. und so weiter

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

und in Global.asax:

   protected void Application_Start()
    {
        ViewEngines.Engines.Clear();
        ViewEngines.Engines.Add(new LocalizedRazor());
    }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top