Localization in a web app using JavaScript and JSON - javascript

I'm trying to set up a script to automatically localize a web application. As the web application is intended to use HTML5's offline caching ability, it needs to be able to work offline. As such, JavaScript seems to me to be the best option.
I'd prefer to put all the strings for all localizations in a single JSON file like so:
{
"en": {
"application_description": "This is the application's description in English.",
"application_name": "This is the application's name in English."
},
"ja": {
"application_description": "This is the application's description in Japanese.",
"application_name": "This is the application's name in Japanese."
}
}
I was thinking maybe of giving all elements that will be localized a custom attribute linking to the intended message (eg: i18n="application_name").
I can retrieve the browser's language using navigator.language, though I think some results will have to be split into just their first section (eg: "en-US" "en-GB" and "en-AU" should all refer to "en").
However, my JavaScript knowledge is basic, and while I've thought about it, I cannot determine how to actually implement this.
Many thanks to anyone who can offer any tips or examples!

You can use Wikimedia's JQuery.i18n.
Documentation: https://github.com/wikimedia/jquery.i18n/wiki/API
Demo: http://thottingal.in/projects/js/jquery.i18n/demo/
Message Syntax: https://github.com/wikimedia/jquery.i18n/wiki/Message-Syntax

http://keith-wood.name/localisation.html
https://github.com/coderifous/jquery-localize
I don't have any personal experience in either but both appear to be fairly well documented.

Depending on your needs, the jquery-localize function might work well. If you need a more complex structure that mirrors that of your website, the localize library might be more useful: https://github.com/kflorence/localize

Related

Internationalization in Vue.js

What are the best practices for internationalization in Vue?
Currently I'm thinking of having a 'strings' object that contains all strings, then a bit of ajax magic to update that strings object based on a json file with translated strings to certain languages.
Anyone got any better ideas? I'm currently having a bit of trouble using my strings approach since the strings object has to be loaded before anything else.
Is there a placeholder functionality for strings in Vue? For example, I have a menu whose entries reside in my vm's data. Is there a way to set that to a static string and then automatically bind that to another string once it exists?
The vue-i18n plugin is pretty good. They have documentation that follows the standard set by the Vue documentation. The package is kept up to date as well. I would start there.
One thing I like is their support for single file components. You can add an additional tag to the component with component specific translations. Here is the example from their documentation:
<i18n>
{
"en": {
"hello": "hello world!"
},
"ja": {
"hello": "こんにちは、世界!"
}
}
</i18n>
You might read this article...
I would recommend looking into a i18n lib that is ready to be used in different frameworks, i.e. i18next
There is some vue libs too: i.e. vue-i18next or #panter/vue-i18next
Further you should not only consider that you have to instrument your code (i18n) to get your app/website translated. You should think about the process too - how will you solve continuous localization, how you keep track of progress, etc...
For a translation management+ system you might eg. have a look at locize it plays well with all json based i18n frameworks... and provides a lot more than traditional systems.
Another possibility is vuex-i18n, if you want to use the Vuex store. It defines a method and a filter:
{{ 'Item' | translate }}
{{ $t('You have {count} new messages', {count: 5}) }}

Gulp task to translate JS

I'm working on a JavaScript app and have so far entered all my strings as plain text.
This is starting to feel really hacky (I'm used to gettext) so I'd prefer to wrap them all in something like {{translatable_string}} and have a gulp task just search/replace them all during the build step.
So, my question is; is there a generic (no framework-specific like angular-gettext or something like that) gettext replacer out there?
Obviously it doesn't even have to be connected to JavaScript in any way, you should be able to run it on any file type and have {{translatable_string}}:s be translated.
You may want to look into using gulp-replace. As they explained in this answer, you should be able to use it to find and replace any string that you want in the stream.
I suggest a database of strings for your translations if dynamic generation of page content is possible for your app. Starting with English or whichever is normal but the need to localize content is a tough issue without a robust system. A simple MongoDB table can be used to store the content, and when the app needs an interface it can be loaded with the right localized strings. As a for instance:
if(err) alert("Please turn off caps lock");
could become:
if(err) alert(Please_turn_off_caps_lock.English);
If you are needing to build static pages with gulp, a database in conjunction with gulp-replace sounds interesting. Using gulp-data to call up and package the strings, you can then feed it to gulp-replace and alter the files. The extensible nature of databases or document stores enable you to expand your localization without hacking on individual files or trees all the time.
Try gulp-gettext-parser.
var gettext = require("gulp-gettext-parser");
var rename = require("gulp-rename");
gulp.task("gettext", function() {
return gulp.src("src/**/*.js")
.pipe(gettext())
.pipe(rename("bundle.po"))
.pipe(gulp.dest("dist/"));
});
Perhaps what you need is mustache.js, take a look: https://github.com/janl/mustache.js/
I'm not used to work with mustache, but I had to do some updates in a project done with it, and I was surprised the capabilities it have.
If you're familiar with jade (now renamed to pug), you'll find is something similar but at the end, you're not forced to generate only html files, you cand generate any kind of text file.
This blog could be helpful to understand the differences between some other templating languages over Nodejs: https://strongloop.com/strongblog/compare-javascript-templates-jade-mustache-dust/

Localize / Internationalize Static & Dynamic Content, Client Side

Been trying to figure out a solution to internationalize a shopify store. Would really like to use JS or jQuery and switch languages instantly/client side without a reload using JSON-files for storing all language snippets..
There are a couple of really smart options (like localizejs.com), but they are rather expensive over time. Ideally we do not even need a super fancy backend and wouldn't mind "just" editing the language-files manually.
JSON could look like this:
{
"english": {
"Cart":"Warenkorb",
"Products":"Produkte",
"Contact":"Contact"
}
We appreciate any solution you can recommend! We need to be able to replace strings that contain elements like "href" as well though:
<div class="lang“>Replace <a href="#“>a Link</a></div>
How is this tackled usually?
Nowadays people are trying jQueryi18n plugin. May be you can check whether it can suffice your requirements. Its minified version size is upto 5KB. Its very easy to use in your project.
http://www.SiteTran.com/ will enable you to switch languages on the client side, and it's free. It also can provide usable SEO urls (for your HREF's) and it only requires a snippet of javascript for integration.
If you want to do it on your own, you can just simply a JSON file with all of the translations and then with javascript load the text based upon the language.

Infrastructure and internationalization for web app(s) using JSON only API

Here is what I intend to build:
There is a service providing data with RESTful JSON-only API. The server setup is Python + Flask.
There are several clients making use of this API, like a normal web app, mobile-compatible client and a Facebook App.
Now, my assumptions/decisions:
I decided on the server providing only data through JSON, thus handing over the presentation completely to the client-side.
I desire to make the web app mobile compatible, thus eliminating need of a separate mobile client.
Also, for Facebook app, I decided to use Facebook Canvas, which would render parts of the normal web app, thus reusing the code.
Feel free to correct me if anything is wrong in above assumptions. Though the above is theoretically possible, I would like to know if the practical implementation is feasible or not.
Now, the web app, after having fetched the base page/template from server, will have to handle the rendering dynamically after fetching data through JSON API. The data is quite simple: multiple-option questions, answering which user receives another question. At the end, user can share the result or invite other users.
With this setup, do I need a framework like angularjs or jQuery would suffice?
My main concern here is how do I handle internationalization? I initially intended to user Flask-Babel to internationalize HTML templates. But having zeroed in on JSON-only API, I don't have a clue as to how/where I handle it now: on client-side or server-side? What are the tools I use for it?
One approach I could think of was to have data in different languages on server itself, and send the JSON response with data in appropriate language, depending on some attribute the client sends in request.
Another approach is to let client do all the translation for a common dataset that server sends. I am not sure of this approach though.
You could find this plugin really helpful.
As far as the usage , it is quite simple to set it up for a single page application that is powered by a JSON API.
If we take a look at a sample usage :
HTML:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="[PATH]/jquery.js" /> // optional
<script type="text/javascript" src="[PATH]/i18next.js" />
</head>
<body>
<ul class="nav">
<li></li>
<li></li>
<li></li>
</ul>
</body>
Json (loaded resource):
{
"app": {
"name": "i18next"
},
"nav": {
"home": "Home",
"page1": "Page One",
"page2": "Page Two"
}
}
JS:
i18n.init(function(t) {
// translate nav
$(".nav").i18n();
// programatical access
var appName = t("app.name");
});
https://github.com/wikimedia/jquery.i18n may be close match. It can handle a lot of languages and messages are in json files and it is complete client side library.
If all of your interface code lives on the client side, so should your i18n. You would use a i18n library that works with the JavaScript framework you are using. For angular, that might be angular-gettext.
If you are developing several client you might use different i18n libraries in different client applications. Try to make sure they all compile gettext .po files – it will make it easier for your translators.
Using jQuery, Angular, etc. is a decision you should make based on your comfort with the technology, the needs of your application, and compatibility with the Facebook Canvas approach. Angular has powerful data binding, but it requires a mind shift compared to jQuery, for instance, so I suggest poking around with each to see if they meet your needs.
As for internationalization, you can use a plugin like jQuery.i18n, or you could roll your own, something I have done with jQuery and jQuery.Mustache for templating. The short version is that you use HTML templates to store your layout, then render them from inside jQuery like so:
var data = {myLabel: 'Some label', myOtherLabel: 'Some Other Label'};
$("#myDiv")
.html( $.Mustache.render( "MyTemplateId", data ) );
in html template:
<script type="text/html" id="MyTemplateId">
<div>
<label for="myInput">{{MyLabel}}</label> <input name="myInput" id="myInput type="text"/>
<label for="myOtherInput">{{MyOtherLabel}}</label> <input name="myOtherInput" id="myOtherInput type="text"/>
</div>
and on your page layout:
<div id="myDiv>
<!-- dynamic content inserted here -->
</div>
You use a loader command with jQuery.Mustache (https://github.com/jonnyreeves/jquery-Mustache) to load your templates from the server, and since you are using templates, you can fill in your values based on user language selection. How you store your internationalized data is dependent on your app. As Michael suggested, if it is a small amount of static content, maybe you just store it all in your JS files as constants and load into your Mustache render() methods as needed. If you have a larger amount/dynamic multilingual content, you should probably store it on the server and load it dynamically. One consideration is the number of languages you plan to support. If you go beyond a handful of languages, consider storing it on the server and loading language data on demand.
I like this approach because it gives you granular, runtime control over your layout and over internationalization. It also stores the data on the server but loads programatically from the client, maintaining a clean separation of concerns for your application layers.
As for responsive/mobile friendly design, using templating (Mustache) and checking the viewport at load time allows you to determine browser capabilities and serve the approrpriate layout without having to prompt the user to select a mobile/desktop experience.
If you go this route, you should also research script loaders like RequireJS and StealJS to handle dependency loading for your scripts, and to handle the initial browser check and layout generation.
Your question is too broad. I can only answer part of it and here are some of the answers:
I desire to make the web app mobile compatible, thus eliminating need of a separate mobile client.
In order to make sure that things are working fine you need to handle
Also, for Facebook app, I decided to use Facebook Canvas, which would render parts of the normal web app, thus reusing the code.
I am not sure.
With this setup, do I need a framework like angularjs or jQuery would suffice?
As you tagged that you are targeting this as a single page application. Therefore, I would recommend you to go for single page frameworks like Anglarjs, knockout.js or Node.js. A quick and good comparison between these frameworks can be found from here
Also this post shares how to implement Internationalization in Angularjs
My main concern here is how do I handle internationalization?
some of these frameworks provide support for handling internationalization and localization natively. For other you can find some links that will help you achieve internationalization.
Whereas if you use jQuery you will to define your own framework for handling single-page-application and apart for that you will need a huge bunch of add-on's to accomplish your objective.
Hope this helps!!!
Steps to implement i18n via js & json:
define css class for i18n tag, e.g. <span class="i18n" id="i18n_username"></span>
define i18n values for different language in different .properties file, e.g. in userhome_en_US.properties, there is a key value: username = Username
write backend API to load .properties file by language, and return in json key-value format, e.g. send param: lang=en_US, page=userhome to I18nAction -> loadI18n(), then it will return json value via ajax: {"username":"Username"},
write js function to load i18n key-value by lang & page param,
update i18n text on web page, by get the tag via css class, and replace content, e.g. use jquery to get all span tag that has class="i18n", then remove the i18n_ prefix of the id, then use it as key to get the value from returned json, then replace the content of span,
I did write util programs like this, it's quite flexible & easy to use. The basic concept is come from struts2 framework's i18n feature.
Although I don't know your technical constraints in detail, I believe it all depends on your volume of data :
If you have few "questions / answers" that probably won't evolve much over time, you can treat I18N as constants. Putting everything on the client side makes sense.
If you have a big amount of "questions / answers" that will probably evolve, I believe you have to treat I18N as data.
Since you have made a JSON API, the odds are that your Q/A is your data, and it already belongs to your server side.
The real question is : do you want to deliver a new version of your client app everytime you add or correct a question?
That's why I would do this :
One approach I could think of was to have data in different languages on server itself, and send the JSON response with data in appropriate language, depending on some attribute the client sends in request.
edit (precision) : I'm talking about the questions and answers. For the application messages (menus, text, help messages, etc), you should use your client framework's i18n components. The other answers provide a lot of good tools.

What is the recommended way to enable multiple language support for Javascript displayed text

A number of times I have needed to support multiple languages when building web sites but have yet to come up with a good way of passing the language strings from the server to the client so that they can be used in Javascript for dialogs, messages, etc.
What are your recommendations or experience with this?
EDIT: I'm leaning towards generating the javascript language files on the fly and would appreciate it if anyone knows any third party libraries that can do this.
I usually move all string specification to separate files and then include the appropriate one on the page, something like this:
In st/js/messages-ru.js:
hello = "Привет"
bye = "Пока"
In st/js/messages-en.js:
hello = "Hello!"
bye = "Good bye!"
When the page is generated, you can determine the language and insert the appropriate js file on the page.
Generate the language dependent portion of javascript on the fly handling locale. For performance cache the language specific javascript, once it is generated for a given locale. This saves from maintaining too many language specific javascripts
We pass an object to the JavaScript method that requires translations, and populate that object from server side code:
<script type="text/javascript">
var dialogl10n = {
caption: '<%= Resources.GetString(x => x.DialogCaption) %>',
okButton: '<%= SharedResources.GetTerm(x => x.Ok) %>'
cancelButton: '<%= SharedResources.GetTerm(x => x.Cancel) %>'
};
</script>
In the javascript function:
Foo.Bar.doSomething = function(l10n) {
alert(l1n0.caption);
}
We're looking at enhancing this to automatically create the JSON object:
onClick='Foo.Bar.doSomething(<%= Resources.GetPackageAsJson(); %>);'
Which would create the equivalent object created by hand above.
no good ways to finish the problem.But i or our team has a heavy method that write different string in js for different language, for instance, in uk we write a js named uk.js and in fr we write a fr.js for static expression in dialogs or messages.
If you're using the ASP.NET AJAX framework, the ScriptManager control contains various mechanisms for automatically generating javascript from localized .resx files, and sending the correct language to the user based on the standard CultureInfo settings that the rest of the website is using. See this MSDN article for a tutorial.

Categories

Resources