views:

1295

answers:

3

I'm working on a web project that is multilingual. For example, one portion of the project involves some custom google mapping that utilizes a client-side interace using jquery/.net to add points to a map and save them to the database.

There will be some validation and other informational messaging (ex. 'Please add at least one point to the map') that will have to be localized.

The only options I can think of right now are:

  1. Use a code render block in the javascript to pull in the localized message from a resource file

  2. Use hidden fields with meta:resourcekey to automatically grab the proper localized message from the resource file using the current culture, and get the .val() in jquery when necessary.

  3. Make a webservice call to get the correct message by key/language each time a message is required.

Any thoughts, experiences?

EDIT:

I'd prefer to use the .net resource files to keep things consistent with the rest of the application.

+2  A: 
RSolberg
Yeah, I'm not a big fan of code render blocks mixed into javascript. One other option I thought of is to load the resource file key/value from a web service as json, then look up the values as I need to.
ScottE
Intersting post here as well: http://www.west-wind.com/Weblog/posts/698097.aspx
ScottE
A: 

I use this technique. It makes it easy for anyone with little coding experience to edit the phrase JavaScript file.

var lang = 0 // 0 = english, 1 = french
var phrases=[]

phrases["plans"] = "Rate Plans and Features|Forfaits et options").split("|")

then you output it as:

phrases["plans"][lang]

...add more columns as required.

Diodeus
Doesn't quite work for me here as I want to use shared .net resource files.
ScottE
+3  A: 

Ok, I built a generic web service to allow me to grab resources and return them in a dictionary (probably a better way to convert to the dictionary)...

<WebMethod()> _    
<ScriptMethod(ResponseFormat:=ResponseFormat.Json, UseHttpGet:=False, XmlSerializeString:=True)> _
    Public Function GetResources(ByVal resourceFileName As String, ByVal culture As String) As Dictionary(Of String, String)

        Dim reader As New System.Resources.ResXResourceReader(String.Format(Server.MapPath("/App_GlobalResources/{0}.{1}.resx"), resourceFileName, culture))
        If reader IsNot Nothing Then
            Dim d As New Dictionary(Of String, String)
            Dim enumerator As System.Collections.IDictionaryEnumerator = reader.GetEnumerator()
            While enumerator.MoveNext
                d.Add(enumerator.Key, enumerator.Value)
            End While
            Return d
        End If

        Return Nothing

    End Function

Then, I can grab this json result and assign it to a local variable:

// load resources
$.ajax({
    type: "POST",
    url: "mapping.asmx/GetResources",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    data: '{"resourceFileName":"common","culture":"en-CA"}',
    cache: true,
    async: false, 
    success: function(data) {
        localizations = data.d;                
    }
});

Then, you can grab your value from the local variable like so:

localizations.Key1

The only catch here is that if you want to assign the localizations to a global variable you have to run it async=false, otherwise you won't have the translations available when you need them. I'm trying to use 'get' so I can cache the response, but it's not working for me. See this question:

http://stackoverflow.com/questions/1033305/cant-return-dictionaryof-string-string-via-get-ajax-web-request-works-with-p

ScottE
nice idea. couldn't that get quite big though?
Chris Simpson
I suppose. It would be better off than writing all the localizations into hidden fields. Code render blocks would have the same issue - all written into the js anyway. The intent was more for interface/validation messages, not big chunks of content or html.
ScottE
You can set up some script that investigates JavaScript files to find out which localized messages are really used there. Then you can send only those messages to JavaScript that are only used there. That would keep the size down. I'm using that kind of approach to bring GNU Gettext into JavaScript, described here: http://stackoverflow.com/questions/431672/how-to-translate-strings-in-js/431744#431744
Rene Saarsoo
Very interesting approach. Again, I don't think I could use this given that I'm relying on shared .net resource files.
ScottE
Ok, I have now implemented this technique. Even though the ajax call has to be run synchronously, it is quite fast, so the blocking is imperceptible. Works just fine!
ScottE