sabato 21 febbraio 2015

Localization with Angular.JS

In a previous post covering the use of Angular.JS on an ASP.NET (or better, DotNetNuke) web app, a was wondering how to solve the problem of localize the js content.

In fact I discovered pretty soon that many strings of the presentation layer were specified inside the js file, defining the angular app, controller, directive,....

So my first thought was to create a specific handler in order to generate the javascript at runtime so that I would have the capability to use the native localization management of ASP.NET or DotNetNuke.

IMHO the handler would have as many cons than pro, or even worst; for example, every js file would have been addressed by the unique handler, breaking the easy file organization of each DNN module or ascx control, ...: much work for a small problem.

So I passed to another approach:
why not concentrate all the strings to localize in a js object inside the ascx file?
the Angular.JS app (controller/directive,...) would be kept in a separate pure js file, with the capability to access the variable once on the client's browser.

The solution is composed by:
1) a method to run on load, in a base class of the module (or User control), with a couple of properties override-able in the specialized module class.

     protected void LoadResourcesToJavascript()
        {
            if (this.ResourceKeysToJavascript.Count() > 0)
            {
                System.Text.StringBuilder sb = new System.Text.StringBuilder();
                sb.Append("var " + this.ResourceJSVariableName + " = {};\n");

                foreach (String s in this.ResourceKeysToJavascript)
                {
                    sb.Append(this.ResourceJSVariableName + "." + s + "= '" + Localization.GetString(s + ".Text", LocalResourceFile) + "';\n");
                }

                Page.ClientScript.RegisterClientScriptBlock(this.GetType(), this.ResourceJSVariableName + "Resources", sb.ToString(), true);
            }
        }

        protected virtual List ResourceKeysToJavascript
        {
            get
            {
                return new List();
            }
        }
        protected virtual String ResourceJSVariableName
        {
            get
            {
                return this.ID;
            }

        }

Note: I use the DNN method to get the localized string. Change it in case of standard ASP.NET project.
Note: The javascript variable name is the control's ID, but it can be specialized in the inherited module class.

2) in the inherited module / user control specialize the ResourceKeyToJavascript list with the resource string required in the javascript.

 protected override List ResourceKeysToJavascript
        {
            get
            {
                return new List() { 
                                "ConfirmRemoving",
                                "SailingName",
                                "Types",
                                "UnableToFindFriend",
                                "Saved",
                                "Error"};
            }
        }

3) in javascrpit file use the variable name (ASP.NET control's ID) to access the single resource strings:

var str = CrewMemberCollectionV2View.ConfirmRemoving;
if (confirm(str.replace("{sailingName}", entity.SailingName))) {
     //do something  
}

4) last but not least, use the standard resx files to add the required resource strings.

1 commento:

Greg David ha detto...

Hello! To easily handle your localization projects, I suggest to have a look at https://poeditor.com/ which is a collaborative translation management platform created to simplify the workflow.