Wednesday, December 29, 2010

Dojo Custom Builds with Localized Resources

I have been building a mapping application using the ArcGIS API for Javascript which is built on dojo.  My application uses localization and enough custom wijits to justify a custom build.  I have been struggling with getting the custom build to work.  The resources I defined were trying to load from http://serverapi.arcgisonline.com/jsapi/arcgis/2.1/js/dojo/dojo/nls/myresources_en-us.xd.js instead of my own server.

The fix I stumbled upon was to register a module path to redirect "dojo.nls" before loading my layer:

        <script type="text/javascript">
            dojo.registerModulePath("dojo.nls", "http://myserver/dojo/dojo/nls")
        </script>
        <script type="text/javascript" src="http://myserver/dojo/dojo/coretech.xd.js.uncompressed.js"></script>

I found this fix by substituting the  obfuscated esri build (<script type="text/javascript" src="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=2.1"></script>) with the uncompressed build from AOL (<script type="text/javascript" src="http://o.aolcdn.com/dojo/1.5/dojo/dojo.xd.js.uncompressed.js"></script>).
 
I then put a breakpoint on dojo.registerModulePath("dojo.nls", "http://sarah-pc/dojo/dojo/nls") to get into dojo.xd.js.uncompressed.js and searched for the implementation of _preloadLocalizations.  I chose this method because the bottom of my custom build contains a call to it:

dojo.i18n._preloadLocalizations("dojo.nls.coretech", ["ROOT","ar","ca","cs","da","de","de-de","el","en","en-gb","en-us","es","es-es","fi","fi-fi","fr","fr-fr","he","he-il","hu","it","it-it","ja","ja-jp","ko","ko-kr","nb","nl","nl-nl","pl","pt","pt-br","pt-pt","ru","sk","sl","sv","th","tr","xx","zh","zh-cn","zh-tw"]);

I set a breakpoint on preload() in that method:

dojo.i18n._preloadLocalizations = function(/*String*/bundlePrefix, /*Array*/localesGenerated){
    //    summary:
    //        Load built, flattened resource bundles, if available for all
    //        locales used in the page. Only called by built layer files.

    function preload(locale){
        locale = dojo.i18n.normalizeLocale(locale);
        dojo.i18n._searchLocalePath(locale, true, function(loc){
            for(var i=0; i<localesGenerated.length;i++){
                if(localesGenerated[i] == loc){
                    dojo["require"](bundlePrefix+"_"+loc);
                    return true; // Boolean
                }
            }
            return false; // Boolean
        });
    }
    preload();    var extra = dojo.config.extraLocale||[];
    for(var i=0; i<extra.length; i++){
        preload(extra[i]);
    }
};

Once there I confirmed the parameters (bundlePrefix="dojo.nls.coretech") and stepped through the code.  I stepped into the dojo["require"] call and found that it does attempt to resolve "dojo.nls.coretech_en-us" as a module prefix.  The next prefix is "dojo.nls", which is easier to maintain. 

You would think I would have been better off putting my resources one level deeper and used a compound namespace to identify them.  For example, if I instead used dojo.requireLocalization("coretech.dijit", "resources") and moved my "nls" folder under the coretech/dijit folder I could have registered the module path against "dojo.nls.coretech" instead of "dojo.nls" but that is actually not the case.

I know it's possible to do this correctly as evidenced by the ESRI API - dojo.i18n._preloadLocalizations("esri.nls.jsapi", ...).  I just don't know how it was done.

No comments:

Post a Comment