I Googled some days for a solution for tranlating JavaScript string placed in external files without finding any simple solution. I found many solutions that store resource in separate files or store translated strings in dictionaly. This solutions was not perfect in my scenario becouse store all translated strings in client browser also when the usere require only a language.
Another reason is that in all this solution you need to reference a translated string by reference a special variable like (progect.translation.testMessage['it-IT']
).
I think that the user need only his language strings on the client js file and I prefere to use a string like this @Cult.Text("ID") in the JavaScript code.
First Statement: Why not use the MVC Razor view engine to render the javascript external file script ?
I create a JsController.cs:
public class JsController : Controller
{
public JavaScriptResult Index(string js, string lang, string ver)
{
Response.ContentType = "text/javascript";
var script = RenderRazorViewToString(js, null);
var jsRet = new JavaScriptResult();
script = script
.Replace("<script type=\"text/javascript\">", string.Empty)
.Replace("<script>", string.Empty)
.Replace("</script>", string.Empty);
var javaScriptMinifier = MinifierFactory.Get<JavaScriptBundle, JsMinMinifier>();
string minifiedJavaScript = javaScriptMinifier.Minify(script);
jsRet.Script = minifiedJavaScript;
return jsRet;
}
private string RenderRazorViewToString(string viewName, object model)
{
ViewData.Model = model;
using (var sw = new StringWriter())
{
var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
viewResult.View.Render(viewContext, sw);
viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
return sw.GetStringBuilder().ToString();
}
}
}
Then in the Views folder I create a test.js.cshtml view. In this view you can generate your javascript libraries using all power of razor engine (Why not??) You can also create a separate file for a different library and you can use intellisense by adding <script></script> tags tha are removed when rendering the view.
The view is also minified with Squishit
@{
Layout = "";
}
<script type="text/javascript"> function Test() {
alert("@Cult.Text("TEST")");
return false;
};
</script>
In _Layout.cshtml I refer to the script (calling the controller) passing it the current language and version only to manage the cached client file.
You need to manage the cache by creating a Helper to generate the controller path (Use reflection to generate the version of the assemply):
<script src="<a>/Js?js=test.js&lang=@Cult.CurrentCulture()&ver=1.4</a>" Type="text/javascript"></script>
I use this great solution to store the current user culture into a cookie and get it server side: Is it safe to use an HttpModule for localization?
I create a Cut class the manage the translation system, this is a simple implementation you can use resource or other system to translate your strings:
public static class Cult
{
public static string CurrentCulture()
{
return System.Threading.Thread.CurrentThread.CurrentCulture.Name.Substring(0, 2).ToLower();
}
public static string Text(string messageID)
{
var currentCulture = System.Threading.Thread.CurrentThread.CurrentCulture.Name.Substring(0, 2).ToLower();
var defaultMessage = string.Empty;
if (messageID == "TEST")
return currentCulture == "it" ? "Testo di prova in Italiano" : "Text message in English";
return currentCulture == "it" ? "Clicca qui per effettuare il test di localizzazione" : "Click here to test the localization";;
}
}
That's it!! I create a system that permit you to manage your external javascript files and use localizations on it.
The sample is in the attachment file... plese update all referenced packages with NuGet.
The comments are much appreciated.