13

I want JavaScript code to be separated from views.
I got the requirement to implement localization for a simple image button generated by JavaScript:

<img src="..." onclick="..." title="Close" />

What's the best technique to localize the title of it?

PS: I found a solution by Ayende. This is the right direction.

Edit:
I got Localization helper class which provides the Controller.Resource('foo') extension method.

I am thinking about to extend it (helper) so it could return all JavaScript resources (from "ClientSideResources" subfolder in App_LocalResources) for the specified controller by its name. Then - call it in BaseController, add it to ViewData and render it in Layout.

Would that be a good idea?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Arnis Lapsa
  • 45,880
  • 29
  • 115
  • 195

3 Answers3

9

EDIT

Consider writing the necessary localized resources to a JavaScript object (hash) and then using it for lookup for your dynamically created objects. I think this is better than going back to the server for translations. This is similar to adding it via viewdata, but may be a little more flexible. FWIW, I could consider the localization resources to be part of the View, not part of the controller.

In the View:

<script type="text/javascript"
         src='<%= Url.Content( "~/Resources/Load?translate=Close,Open" %>'></script>

which would output something like:

var local = {};
local.Close = "Close";
local.Open = "Open";

Without arguments it would output the entire translation hash. Using arguments gives you the ability to customize it per view.

You would then use it in your JavaScript files like:

 $(function(){
     $('#button').click( function() {
        $("<img src=... title='" + local.Close + "' />")
           .appendTo("#someDiv")
           .click( function() { ... } );
     });
 });

Actually, I'm not too fussed about keeping my JavaScript code out of my views as long as the JavaScript code is localized in a container. Typically I'll set my master page up with 4 content area: title, header, main, and scripts. Title, header, and main go where you would expect and the scripts area goes at the bottom of the body.

I put all my JavaScript includes, including any for viewusercontrols, into the scripts container. View-specific JavaScript code comes after the includes. I refactor shared code back to scripts as needed. I've thought about using a controller method to collate script includes, that is, include multiple scripts using a single request, but haven't gotten around to that, yet.

This has the advantage of keeping the JavaScript code separate for readability, but also allows me to easily inject model or view data into the JavaScript code as needed.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
tvanfosson
  • 524,688
  • 99
  • 697
  • 795
  • "I want javascript to be separated from views." == "Also a good practice to keep your javascript separate from your mark up.". <= and that's the problem why <%= foo %> won't work. – Arnis Lapsa Jul 06 '09 at 13:03
  • Btw, why attaching onclick handler on JS onload is preferable? – Arnis Lapsa Jul 06 '09 at 13:05
  • I missed the "generated by JS" part of your question -- just scanned right over it. In this case, I would consider writing the localized data to the view and having the javascript load it from a local object. Will rewrite. – tvanfosson Jul 06 '09 at 13:35
  • It's quite possible that you missed it cause i edited my question (~5 seconds after i submitted it) to add it. :) – Arnis Lapsa Jul 06 '09 at 13:45
  • @Arnis -- re: adding onload. That comment was made when I thought you were rendering the element inline. I prefer using the click() method to add handlers rather than doing it via element attributes when adding dynamically. See my updated answer for an example of how to use the localized resources when creating an element dynamically. – tvanfosson Jul 06 '09 at 14:08
  • It looks quite fine but would add one more HTTP request, right? On the other hand - this problem I've solved already (can merge, compress and cache it). Instead of arguments, it seems better to organize JS resources per view (not forgetting shared ones) and just reference them. And what about that onclick handler on JS onload? What's the benefit? :) – Arnis Lapsa Jul 06 '09 at 14:11
  • Check out this one - http://weblogs.asp.net/rashid/archive/2009/05/02/script-and-css-management-in-asp-net-mvc-part-2.aspx It works like a charm. And thanks for answers. When I'll be done with this, I'll add my solution in question and (if no one is going to beat you) accept your answer. :) – Arnis Lapsa Jul 06 '09 at 14:15
  • Interesting post -- I'd think about having the returned object implement IDisposable, though so I could put it in a using block (like the Html.Form helper extension) and omit the explicit call to Render. – tvanfosson Jul 06 '09 at 14:30
  • Still haven't started to implement this (was deep into refactoring) and won't start doing it yet. But i noticed that i won't be able to reduce that 1 http request. :/ – Arnis Lapsa Jul 08 '09 at 20:44
2

Actually ASP.NET Ajax has a built-in localization mechanism: Understanding ASP.NET AJAX Localization

Nightfirecat
  • 11,432
  • 6
  • 35
  • 51
brunosp86
  • 670
  • 1
  • 10
  • 21
1

If you insist on keeping it separate, you could do something like:

//keep all of your localised vars somewhere
var title = '{title_from_server}';
document.getElementById('someImage').title = title;

Remember, if you use JavaScript code to initialize any text of elements, your site will degrade horribly where JavaScript isn't available.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
karim79
  • 339,989
  • 67
  • 413
  • 406