Share localization strings with JavaScript backend

Consider a JSP application with multiple JavaScript files. The backend is fully localized using multiple files .properties

, one for each language. The HTML provided contains strings in the correct language - this is all common stuff and works great.

Now, however, from time to time I need to use some localized string in a JavaScript resource. Suppose for example:

function foo() {
  alert('This string should be localized!');
}

      

Note that this is somewhat similar to the need to reference some AJAX endpoints from JavaScript, which is handled well by the reverse JS router. However, the main difference is that the backend does not use a router, but uses strings.

I have come up with several approaches, but none seem to be good enough.

Parameters

The JSP that outputs the code to call foo()

will select the line:

foo('<%= localize("alert.text") %>');

function foo(alertText) {
  alert(alertText);
}

      

Pros: It works. Cons: Method signatures are bloated.

Prototypes

JSP displays hidden range with string, JS selects it:

<span id="prototype" class="hidden">This string should be localized!</span>

function foo() {
  alert($('#prototype').text());
}

      

Pros: Method signatures are no longer bloated. Cons: Make sure the hidden <span>

one is always present.

AJAX

There is an endpoint that localizes strings by their key, JS calls it. (The code is approximate.)

function foo() {
  $.ajax({ url : '/ajax/localize', data : { key : 'alert.text' } })
      .done(function(result) {
          alert(result);
      } );
}

      

Pros: The server has full control over the localized result. Cons: One HTTP call per localized string! Any of the AJAX calls fail, the logic breaks.

This can be improved by getting multiple lines at once, but the problem with rountrip is significant.

Shared properties files

The properties file containing the current language is simply displayed as an additional JS resource on the page.

<script src="/locales/en.js" /> // brings in the i18n object

function foo() {
  alert(i18n.alert.text);
}

      

Pros: Fast and reliable. Cons: all lines are pulled in - also those that we don't need or don't want to show to the user.

This can be improved by keeping a separate rowset for JS, but this violates the DRY principle.

Now what?

So these are the ideas that I had. None of them are perfect, all have their share of problems. I am currently using the first two approaches with mixed success. Are there any other options?

+3


source to share


1 answer


Your idea with a shared properties file is the neater solution of the 4 ideas you suggested. A popular CMS I use, called Silverstripe, actually does the same thing , downloads a localized JS file that adds strings to the dictionary, allowing for a common API to fetch strings.

The comments talk about including localized strings for a particular kind. While this might have some use in specific situations where you have thousands of lines to localize (over a few hundred KB in total), it might also be a little overkill.

client side

Depending on how many other JS resources you are loading at the same time, you may not need another view request to add a few more lines for that locale. Each view localization must be requested separately, which can be a little ineffective. Give the browser all the localizations in one request and let it just read its cache for each view.

A browser caching the full set of locale strings can result in a better user experience with faster page load times with one fewer requests per view. For mobile users, this can be very useful, even with a faster mobile internet, and not every request is lightning fast.

server side



If you follow the method suggested in the comments, having a file locale.asp

that generates JS locale strings on the fly, you are giving the server a little more work for each user. It's not too bad if every user asks for it once, if it's a view request it can start adding up.

If the user is viewing 5 different pages, this is 5 times the server is executing the JSP, generating data for a specific kind. While your code can be a basic if statement and load multiple files from the filesystem, there is still the overhead of executing that code. While this may not be a problem, say at 10 requests per minute, it can lead to problems with 1000 requests per minute.

Again, the extra overhead can be small, but just not necessary unless you really want many small HTTP requests instead of a few large HTTP requests and a little browser caching.

Additional thoughts

While this may seem like a premature optimization, I find it simple and important. We don't know if you have 5 users or 5,000, if your users will see 5 different views or 500, if you will have many / any mobile users, how many locations you want to support, how many different strings for each locale.

Because of this, I think it is best to see a bigger picture of what the choice will make that the locale strings loaded per view will be loaded.

+1


source







All Articles