Reputation: 2052
I've build a web application based on RactiveJS. It uses RequireJS to handle modules and dependencies. Ractive Templates are loaded with rv.
Now I'd like to support multiple languages (initially only german and english).
So my question is:
So far I see two options:
1. Strip all text from templates, put them in a resource file and pass em through a lookup-method.
Downsides:
Either brakes text apart leaving meaningless chunks or breaks data binding in cases like <div>The Item {{name}} is used <b>{{count}}</b> times.</div>
2. Duplicate Templates
Downsides:
• duplicated template-code
• Could not figure out how to build separate language packages for the templates with RequireJS-Optimizer
3. ???
Any other ideas?
BTW: It is ok, to reload the entire app when the language changes. I'd prefer a solution where only resource for currently selected language will be loaded through RequireJS.
Upvotes: 2
Views: 484
Reputation: 1255
To address the problem of 1 + 2, namely to keep your templates meaningful while not duplicating all templates, consider providing the text of your primary language (let's say English) as default to the translation function.
Based on the discussion in this Ractive issue, and demonstrated by kurdin in this fiddle, your template might look like so:
<p>{{{ t('Hello <strong>{{name}}</strong> and have a nice day!', 'hello', {name: user.name}) }}}</p>
Then, you'd define a translation function t
that handles the default specially.
Translations = [] // load those however you want
Translations["ru"] = {
localization: 'пример локализации',
hello: "Привет <strong>{{name}}</strong> хорошего тебе дня!",
language: 'Язык: {{lang}} ',
lang: 'Русский'
}
I18n.translations = Translations;
I18n.defaultLocale = "en";
function t(defaultText, name, context) {
return (I18n.locale === I18n.defaultLocale) ? defaultText : I18n.t(name, context);
}
The downsides are:
To address the first problem, i.e. consistency, you might want to provide a language pack for English, too, and skip the custom t
function.
Upvotes: 2
Reputation: 119847
There is no canonical way to do this. However, you could get away with it by using decorators. Wrap text in a <span>
and add a decorator to the <span>
. What the decorator does is fetch the <span>
's contents, get the translation from a prepared mapping, and replace that text.
<div>
<span decorator="i18n">Some random text to translate</span>
</div>
To generate translation files, you can have a grunt/gulp/whatever tool task that runs through all your component files, parse the HTML part of it and look for elements with the decorator="i18n"
. You then generate your JSON template off of it, and you manually fill in the translations.
{
"Some random text to translate": "Alcuni testo casuale da tradurre",
...
}
You can then have some global indicator of some sort to signal the decorator module what translation mappings to load in. Since translation can be changed any time, it can't be loaded via RequireJS statically. The mappings will need to be AJAX'ed down or done via a dynamic require
call. Either way, translations will not be included by the optimizer.
Additionally, there's a bit of overhead in rendering, as every component that's rendered with that decorator will change the text on the fly.
Upvotes: 2