Локализованные виды с Razor - PullRequest
3 голосов
/ 22 ноября 2010

Я пытался быть остроумным и использовать 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 / Пользователь / Details.sv.cshtml

Hejsan @Model.FirstName

Detta är en lite rolig text på svenska.

/ Views / Пользователь / Details.en.cshtml

Hello @Model.FirstName

This is a test on english.

Контроллер

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

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

Ответы [ 3 ]

5 голосов
/ 22 ноября 2010

Вот моя реализация. Его можно сделать более общим, но он отвечает всем моим требованиям.

Сначала я ищу наиболее специализированное представление и пробую без указания языка.

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

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



    }

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

2 голосов
/ 22 ноября 2010

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

1 голос
/ 05 апреля 2013

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

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

.. и т. Д.

    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());
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...