We've decided to add support for multiple languages to our web app.
We use Handlebars for templating on the front end, and Node + Jade for templating on the back-end.
For strings that are not stored in the database (all of the strings that are part of the UI), is there a recommended way of going about this? (Does it make any difference whether we add the strings to the templates on the front-end or the back-end?).
One approach I have taken with javascript-based localizations is to create a collection of files (one file per language), each containing a language object that could be loaded either client side or in node to provide the localizations. You just load the file needed based on the language.
This is a simple example:
var localization = {
stringkey1: 'Some string value',
stringkey2: 'Some other value',
// etc.
}
Obviously if you have a large application with lots of strings, you may want to further break up the localizations so you don't need to work with excessively large objects.
The good thing with this approach is that you could use the same localization library both server-side and client-side without any modification.
Related
I'm developing a web application with Go on the server, and the router will use PushState, so the server will also have to be able to render my templates. That means that I'll need a templating engine that works with Go and Javascript. The only one I've come across so far is Mustache, but it doesn't seem to be able to handle lowercase properties of structs, and there also doesn't seem to be a possibility to provide custom names like JSON:
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
So, is there a templating engine that is available in both Go and JavaScript, and that can handle lowercase struct properties?
As the comments above state, you can't expect any 3rd party library to be able to read lowercase properties on your struct, but it appears you are trying to use tags to represent alternative representations of your struct (as you can with the encoding/json library).
What you can do is use something like github.com/fatih/structs to convert your structs to maps and then range through to lowercase all of your keys (copying the values and removing the uppercase versions) and pass it into mustache.Render() as your context. If you want to use struct tags like the encoding/json library does, you'd have to use the reflect package and write a struct-to-map function that takes into account the tags on the struct (basic example given in the documentation here). There are some SO answers on how to write a struct-to-map function using reflection, which you can improve upon to add struct tag handling as you need.
To answer your question, I don't think this is something a current templating library does that also works with javascript, but it shouldn't be too hard to get working with mustache given the idea above.
I'm a fairly well versed programmer, so learning new technologies shouldn't be that big of an issue. That being said I'm currently attempting to make a card game in HTML5 using canvas/javascript etc.
The current question that I have is what to use to store instances of the cards. I was thinking about using XML to store the card data, but I'd like to limit the amount of work the browser has to do so the game runs more smoothly, I've heard JSON is a good alternative, but I'm just looking for suggestions. Thanks!
JSON is better in my opinion.
You can serialize objects to JSON at server side and send JSON string to client (browser), then your client will be able to parse JSON string into regular JavaScript object using JSON.parse.
In this way you'll not need to walk through XML to find particular nodes, but will just work with data in more convenient way using native JavaScript objects/arrays.
Also in most cases JSON will be more compact than XML so this can save bandwidth and speed-up data loading.
Also the data types stuff may be important here - JSON represents datatypes correctly (integers, booleans, floats, strings) and XML is storing them as strings so you'll need some additional attributes to set datatype during serialization and determine it during deserialization.
I am not sure how to do this without a framework, but what I would do is use Backbone.JS and create a model of what an instance would look like. Eg:{CardNumber:'2', CardColor: 'red', CardClass: 'hearts'}. Now I would create a collection to hold all these models, see backbone collections.
So I would store all this data client side, and possibly provide the user with an option to save the game, to persist this data to a database. This stores it as JSON and then when you persist it to the database, you can serialize it to get the individual components.
If you dont want to save to the db and do not want to use a framework. Try stack/queue implementations in Javascript. See:How do you implement a Stack and a Queue in JavaScript?
I hope that answers your question.
Stick to JSON because JSON is just a string representation of plain JS objects, and browsers are very comfortable with it. JS have no good XML handling and that will be too expensive.
Use HTML5 localStorage for keeping data until you really need to sync with the server. Frequent server operations will cause your game to suffer. Use bulk data transfers instead of many small server connections (for example at the start and the end).
Consider using a game library if the canvas graphics are intense. I have used http://jawsjs.com sometime back, but there should be better libs available out there. Selectively render only the dynamic objects, not everything on canvas.
JSON in conjunction with localStorage is a great way to go.
There are libraries available to serialize and deserialize Javascript objects and allow you tp store and retrieve it from localStorage. Simple Github search is a good way to start
In a distant future I'd like to distribute my multilingual single-page-application, containing all sorts of resources (videos, texts, interactive applications), for both the web and for the desktop (offline). That dream scenario would also allow translators to access a unified translator dashboard, from where all translations, for all formats, could be crowdsourced.
But that is the future.
What I'm looking for short-term is instead an efficient solution for integrating i18n into my JavaScript templates. There should also be some method that can be used when templating is not an option, i.e. when SVG text elements (that should hold translated strings) are added dynamically.
I'm not sure about the pros and cons of doing this server-side (i.e with node.js) - please enlighten me - but it would be nice if the data storage could easily be swapped (from database to files etc.) in case the offline delivery mechanism does not come with database support.
Where should I start, and is there any path that will allow me to build the i18n system incrementally without having to shift the whole paradigm when going from small-scale to big?
An idea could be to define a global shortcut like mapping (for instance) _ (underscore) to the translation method of i18n plugin/library whatever s.t. you can then from your JavaScript code (and thus also from within your template) execute calls like
_("textToLocalize")
which will return the correctly localized text based on the current language.
This method could then contact a REST service (with proper caching) for retrieving the localized strings from the server where they're somehow managed in files/db tables.
I'm developing a HTML5 application that uses jQuery. I want to make it multi language: detecting user language and changing all literals to user's language.
I think that one approach is to use one HTML file for each language supported, but it is a waste of space.
Another approach could be use jQuery to change all literals to user's language. But I'm not sure how to do this.
What do you think? Is there a better approach?
UPDATE:
I've forget it to say that I have some literals inside JavaScript too.
Coulnd't you do some sort of server-side query to the user's language and then load the appropriate text automatically? Maybe even a CMS is appropriate here.
For all the Javascript code, I would use String literals as a variable. So you can load a different language file appropriate to the user language.
File english.js:
var messages_siteA1 = "This is an alert.";
var messages_siteA2 = "...";
// ...
File german.js:
var messages_siteA1 = "Dies ist eine Warnung.";
var messages_siteA2 = "...";
// ...
And in your Javascript:
alert(messages_siteA1);
Or am I missing the point here? ;)
In the HTML5 Demo of my, the "HTML5 Word Clouds",
http://timc.idv.tw/wordcloud/
(source code can be found at https://github.com/timdream/wordcloud)
I wrote separate HTML for different languages, and includes a single set of Javascript files. For literal strings with in the script, I collect them into an object (named T) and put it into <script> block of each HTML files.
This give me the flexibility to customize pages for each language; as you can see, I listed CNN as example in English version, but list other sources in the Chinese version.
If you absolutely have to do it at client-side, how about using a json or xml file to store your translations? This avoids the trouble of creating copies of the same page. For example, in your json. you'd have "welcome_eng": "welcome" and "welcome_fr": "bienvenue", etc.
Then you load the appropriate one using javascript, as in, get the variables like this:
blablabla=["welcome_"+language]
Or, if you want even less work, your welcome text's div will have the id "welcome", then your javascript gets the id and add the appropriate content.
It mostly depends on how dynamic or static your pages are: If they contain much text, than it will be easier to duplicate the page for each language. In this case it is very important to carefully isolate HTML from CSS and scripts. All CSS and scripts should be stored in separate pages, in order to avoid having to update all translations whnever you update a style or a script.
OTOH, if it is mostly dynamic, than it makes sense to replace text snippets by their translation when creating the page. But I wouldn't do the text replacement client-side (jQuery). It's a server-side job.
Edit: If you have javascript literals, you should then of course keep them side by side with the HTML, either in the HTML file or in a separate .js file. But it remains up to the server to deliver the contents in the correct language.
I'm trying to determine the best way to implement localization into one of our web apps. This app is going to have a large number of javascript files, which will need to be localized as well.
Localizing the .net code is straight forward enough. We have a file called WebResources.resx which contains all strings in english (our fall back language). Then we just add additional files with alternative localized information (eg: WebResources.es-mx.resx). Then, bam! .Net pretty much takes care of the rest.
Pretty sweet. But when it comes to javascript, not so fast. Reading on MSDN they recommend:
You create a separate script file for each supported language and culture. In each script file, you include an object in JSON format that contains the localized resources values for that language and culture.
This seems like a maintenance nightmare that I'd like to avoid. Plus I'd like to avoid having to use the asp.net ScriptManager. So I got the bright idea of trying to use the resource files in my .js files. EG foobar.js:
function showGenericError(){
alert('<% =Resources.WebResources.JsGenericError %>');
}
This unfortunately does not work as the .NET does not seem to do any processing on .js files. So the next idea I got was from the answer on this thread. It recommended having a javascript file which contained all your language strings. This feels like a waist of resources since at run time I only need one language, not all of them.
This leads me to the solution I'm planning on implementing. I plan to have a generic handler that writes out JSON that is localized for the language the current user is in need of. Here is a sample of what the .ashx page will look like:
public void ProcessRequest (HttpContext context) {
context.Response.ContentType = "application/json";
StringBuilder json = new StringBuilder();
using (StringWriter jsonStringWriter = new StringWriter(json))
{
using (JsonTextWriter jsonWriter = new JsonTextWriter(jsonStringWriter))
{
jsonWriter.WriteStartObject();
jsonWriter.WritePropertyName("genericErrorMessage");
jsonWriter.WriteValue(Resources.WebResources.GenericErrorMessage);
jsonWriter.WriteEndObject();
}
}
context.Response.Write("var webResources = " + json.ToString());
}
In the head of my pages I will have:
<script type="text/javascript" src="js/webResources.js.ashx"></script>
Then my js file will look like:
function showGenericError(){
alert(webResources.genericErrorMessage);
}
Almost seems too easy, right? So my question is, does this make sense? Am I missing a "gotcha" somewhere? What are the downsides? Is there a better way to do this?
I posted a similar question a while ago, and this is what I came up with:
Localize javascript messages and validation text
The advantage here is that you can share resources used in regular .net pages.
Your approach looks fine as well.
Here is the way i did it, just in case someone finds it useful.
I didnt want to put any Razor on JS, because of CSP i kept JS files separated from the cshtml.
So I added a element in the Shared cshtml, with the content of an array of arrays, each element of the array is a Key/Value pair with the name and the localized string as returned by Razor>
<meta name="resources" content="[
['name1', '#HttpUtility.JavaScriptStringEncode(Resources.name1)'],
['name2', '#HttpUtility.JavaScriptStringEncode(name2)']
]" />
Then in the js file, i convert this into a dictionary:
let livstrResMap = document.querySelector("meta[name='resources']").getAttribute("content");
livstrResMap = livstrResMap.replace(/'/g, '"')
let lioJSN = JSON.parse(livstrResMap)
let mcvcodResources = new Map(lioJSN);
Finally i use the localized string using the Format helper defined here
alert(mcvcodResources.get('name1'));