Локализованное решение scriptbundle

Привет. В настоящее время я использую asp.net MVC 4 rc с System.Web.Optimization. Поскольку мой сайт должен быть локализован в соответствии с предпочтениями пользователя, я работаю с плагином jquery.globalize.

Я бы очень хотел создать подкласс класса ScriptBundle и определить, какие файлы объединять в соответствии с System.Threading.Thread.CurrentThread.CurrentUICulture. Это будет выглядеть так:

bundles.Add(new LocalizedScriptBundle("~/bundles/jqueryglobal")
                             .Include("~/Scripts/jquery.globalize/globalize.js")
                             .Include("~/Scripts/jquery.globalize/cultures/globalize.culture.{0}.js", 
                                       () => new object[] { Thread.CurrentThread.CurrentUICulture })
                    ));

Например, если культура пользовательского интерфейса «en-GB», я бы хотел, чтобы следующие файлы были подобраны (конечно, минимизированы и, если возможно, кэшированы до тех пор, пока не изменится файл сценария или культура currentui).

  • "~/Сценарии/jquery.globalize/globalize.js"
  • "~/Scripts/jquery.globalize/globalize-en-GB.js" ‹-- если этот файл не существует в файловой системе сервера, используйте вариант globalize-en.js.

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

public class LocalizedScriptBundle : ScriptBundle
{
    public LocalizedScriptBundle(string virtualPath)
        : base(virtualPath) { 
    }

    public Bundle Include(string virtualPathMask, Func<object[]> getargs) {
        string virtualPath = string.Format(virtualPathMask, getargs());
        this.Include(virtualPath);
        return this;
    }

}

Спасибо

Константинос


person cleftheris    schedule 11.06.2012    source источник


Ответы (2)


Это правильно, пакеты должны быть настроены только перед запуском приложения. В противном случае в сценарии с несколькими серверами, если запрос пакета направляется на другой сервер, отличный от того, который обслуживал страницу, запрос на ресурс пакета не будет найден.

Имеет ли это смысл? По сути, все ваши пакеты должны быть настроены и определены заранее, а не динамически регистрироваться для каждого запроса.

person Hao Kung    schedule 15.06.2012
comment
Да это правда конечно. Но, как кажется, когда файл js или css меняет серверную часть, пакет переоценивается, чтобы быть актуальным (внутри, возможно, с использованием FileSystemWatcher). Я не вижу причин, по которым нельзя было бы переопределить это поведение, чтобы учесть другие события в жизненном цикле приложения, такие как, например, изменение культуры пользовательского интерфейса. - person cleftheris; 18.06.2012
comment
Да, в пакетных ответах настроены зависимости кэша, чтобы аннулировать запись в кэше при изменении файлов в пакете. Мы открываем поведение кэширования для расширения в нашем списке задач, но я не уверен, когда мы до этого доберемся. - person Hao Kung; 26.06.2012

взгляните: https://stackoverflow.com/questions/18509506/search-and-replace-in-javascript-before-bundling

Я закодировал этот способ для своих нужд:

public class MultiLanguageBundler : IBundleTransform
{
    public void Process(BundleContext context, BundleResponse bundle)
    {
        var content = new StringBuilder();
        var uicult = Thread.CurrentThread.CurrentUICulture.ToString();

        var localizedstrings = GetFileFullPath(uicult);
        if (!File.Exists(localizedstrings))
        {
            localizedstrings = GetFileFullPath(string.Empty);
        }

        using (var fs = new FileStream(localizedstrings, FileMode.Open, FileAccess.Read))
        {
            var m_streamReader = new StreamReader(fs);
            var str = m_streamReader.ReadToEnd();

            content.Append(str);
            content.AppendLine();
        }

        foreach (var file in bundle.Files)
        {
            var f = file.VirtualFile.Name ?? "";

            if (!f.Contains("localizedstrings"))
            {
                using (var reader = new StreamReader(VirtualPathProvider.OpenFile(file.VirtualFile.VirtualPath)))
                {
                    content.Append(reader.ReadToEnd());
                    content.AppendLine();
                }
            }
        }

        bundle.ContentType = "text/javascript";
        bundle.Content = content.ToString();
    }

    private string GetFileFullPath(string uicult)
    {
        if (uicult.StartsWith("en"))
            uicult = string.Empty;
        else if (!string.IsNullOrEmpty(uicult))
            uicult = ("." + uicult);

        return Kit.ToAbsolutePath(string.Format("~/Scripts/locale/localizedstrings{0}.js", uicult));
    }
}
person Dantes    schedule 05.05.2014
comment
Как это решение решает проблему динамического изменения культуры потока после создания пакета? - person cleftheris; 07.05.2014