Question

Je suis en train d'être plein d'esprit et d'utiliser un VirtualPathProvider pour trouver des vues localisées. Il prend le chemin de vue requis et modifie lors de la vérification après le fichier. Il retourne un fichier virtuel localisé si elle est trouvée:

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
}

Le problème est que je reçois l'exception suivante:

  

Le VirtualPathProvider retourne un objet VirtualFile avec VirtualPath ensemble à '/Views/Shared/_Layout.sv.cshtml' au lieu de l'attendre '/Views/Shared/_Layout.cshtml'.

Bien sûr, je pourrais faux le chemin du fichier, mais cela produirait des problèmes avec la mise en cache et différentes localisations. Droit?

Quelqu'un at-il une meilleure façon de pouvoir créer des vues localisées? Je ne veux pas utiliser le même point de vue, mais avec des chaînes de ressources au lieu. Ces vues sont si horribles qu'ils me fait presque pleurer parce qu'ils sont si difficiles à lire.

Si vous avez toujours pas compris ce que je cherche:

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

Je veux être en mesure de changer de vue (à l'aide d'un localisé CurrentCulture) sans avoir à faire quoi que ce soit manuellement à chaque demande.

Était-ce utile?

La solution

Vous pouvez écrire un ViewEngine personnalisé qui renvoie des vues en fonction de la CurrentCulture. Un bel exemple de ce qui peut être trouvé à blog de Scott Hanselman , qui fait retour Vues mobiles si la demande a été faite par un appareil mobile

Autres conseils

Voici ma mise en œuvre. Il pourrait être plus générique, mais il répond à toutes mes exigences.

Je cherche la vue la plus spécialisée première et essais sans specfication de dernière langue.

Voir le processus de conclusion:

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



    }

Notez que la mise en cache est désactivée à l'aide de cette approche et vous devrez peut-être créer votre propre cache (pour obtenir la bonne langue)

Voici la plus simple que possible (je suppose) exemple de commutation entre les vues en utilisant la convention suivante:

  1. MyView.cshtml - par défaut
  2. MyView.pl.cshtml - locale polonaise

.. et ainsi de suite

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

et Global.asax:

   protected void Application_Start()
    {
        ViewEngines.Engines.Clear();
        ViewEngines.Engines.Add(new LocalizedRazor());
    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top