Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A localized scriptbundle solution

Hi I am currently using the asp.net MVC 4 rc with System.Web.Optimization. Since my site needs to be localized according to the user preference I am working with the jquery.globalize plugin.

I would very much want to subclass the ScriptBundle class and determine what files to bundle according to the System.Threading.Thread.CurrentThread.CurrentUICulture. That would look like this:

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

For example if the ui culture is "en-GB" I would like the following files to be picked up (minified of course and if possible cached aswell until a script file or the currentui culture changes).

  • "~/Scripts/jquery.globalize/globalize.js"
  • "~/Scripts/jquery.globalize/globalize-en-GB.js" <-- if this file does not exist on the sever file system so fallback to globalize-en.js.

I tried overloading the Include method with something like the following but this wont work because it is not evaluated on request but on startup of the application.

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

}

Thanks

Constantinos

like image 813
cleftheris Avatar asked Jun 11 '12 11:06

cleftheris


2 Answers

That is correct, bundles should only be configured pre app start. Otherwise in a multi server scenario, if the request for the bundle is routed to a different server other than the one that served the page, the request for the bundle resource would not be found.

Does that make sense? Basically all of your bundles need to be configured and defined in advance, and not dynamically registered on a per request basis.

like image 84
Hao Kung Avatar answered Oct 13 '22 12:10

Hao Kung


take a look: https://stackoverflow.com/questions/18509506/search-and-replace-in-javascript-before-bundling

I coded this way for my needs:

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));
    }
}
like image 39
Dantes Avatar answered Oct 13 '22 12:10

Dantes