问题 本地化的scriptbundle解决方案


嗨,我目前正在使用带有System.Web.Optimization的asp.net MVC 4 rc。由于我的网站需要根据用户偏好进行本地化,因此我正在使用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 })
                    ));

例如,如果ui文化是“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;
    }

}

谢谢

康斯坦丁


12091
2018-06-11 11:11


起源



答案:


这是正确的,捆绑应该只应在应用程序启动前配置。否则,在多服务器方案中,如果对捆绑包的请求路由到服务于该页面的服务器之外的其他服务器,则将找不到捆绑包资源的请求。

那有意义吗?基本上所有捆绑包都需要提前配置和定义,而不是基于每个请求动态注册。


9
2018-06-15 22:47



是的,当然这是真的。但是看起来,当js或css文件改变服务器端时,捆绑包会被重新评估以便更新(内部可能使用FileSystemWatcher)。我没有看到为什么人们无法覆盖此行为以考虑应用程序生命周期中的其他事件(例如UI文化更改)的原因。 - cleftheris
是的,捆绑响应具有缓存依赖关系设置,以在捆绑中的文件更改时使缓存条目无效。我们已经开放了缓存行为,可以在我们的待办事项清单上进行扩展,但我不确定何时可以实现这一点。 - Hao Kung


答案:


这是正确的,捆绑应该只应在应用程序启动前配置。否则,在多服务器方案中,如果对捆绑包的请求路由到服务于该页面的服务器之外的其他服务器,则将找不到捆绑包资源的请求。

那有意义吗?基本上所有捆绑包都需要提前配置和定义,而不是基于每个请求动态注册。


9
2018-06-15 22:47



是的,当然这是真的。但是看起来,当js或css文件改变服务器端时,捆绑包会被重新评估以便更新(内部可能使用FileSystemWatcher)。我没有看到为什么人们无法覆盖此行为以考虑应用程序生命周期中的其他事件(例如UI文化更改)的原因。 - cleftheris
是的,捆绑响应具有缓存依赖关系设置,以在捆绑中的文件更改时使缓存条目无效。我们已经开放了缓存行为,可以在我们的待办事项清单上进行扩展,但我不确定何时可以实现这一点。 - Hao Kung


看一看: 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));
    }
}

1
2018-05-05 15:10



该解决方案如何解决在创建捆绑包后动态更改线程文化的问题? - cleftheris