Вопрос

Я пытался быть остроумным и использовать 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.chtml.

Hejsan @Model.FirstName

Detta är en lite rolig text på svenska.

/Views/user/details.en.chtml.

Hello @Model.FirstName

This is a test on english.

Контроллер

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

Я хочу иметь возможность переключать представления (на локализованный с использованием текущейCulture) без необходимости делать ничего вручную при каждом запросе.

Это было полезно?

Решение

Вы можете написать пользовательский ViewEdIne, который возвращает представления в зависимости от текущейCulture. Приятный пример этого можно найти в Сообщение блога Скотта Хансельмана, который возвращает мобильные представления, если запрос был сделан мобильным устройством

Другие советы

Вот моя реализация. Может быть сделано более общедоступным, но он выполняет все мои требования.

Я ищу самую специальное представление сначала и пытается без языкового спецификации последнего.

Просмотр процесса поиска:

  1. Детали .sv-fi.cshtml.
  2. Детали .sv.chtml.
  3. Детали. Den.chtml.
  4. Детали .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;
        }



    }

Обратите внимание, что кэширование отключено с использованием этого подхода, и вам может потребоваться создать свой собственный кэш (чтобы получить правильный язык)

Вот самый простой, как можно (я думаю) Пример переключения между представлениями, используя следующую конвенцию:

  1. Myview.cshtml - по умолчанию один
  2. Myview.pl.chtml - польский язык

.. и так далее

    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());
    }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top