Components localization

Hi I need to support different languages in my components, so I would like to ask a question regarding this.
This is from another my topic, but might be useful here as well:

I have some pre-conditions that I should mention:

Right now the application is old-fashioned multi-page Java application that uses JSP. What we are doing right now is migrating some pieces that we can to canjs. It means that components that I create should have an ability to be used in canjs pages (stache) and in just plain HTML pages with plain JS (or jQuery).

I’m using canjs 2.2.9 I know that its pretty old, but unfortunately this is something that I can’t change in the nearest future.

I created small component (still WIP, but can represent my question):
https://dl.dropboxusercontent.com/u/25491580/can-test/index.html
(Sorry it’s not JSBin because there are different files, folders so it was easier to share in that way, but I can probably post it on Github if its easier than checking sources in devtools)

Basically this is textarea that should count amount of characters, change height and react when character limit exceeds (twitter / facebook like).

I would like to have an ability to use translated properties inside templates. Such properties can contain string with params like: Hello ${username} bla bla bla ${author}. Such strings may have different word order depends on language. Straightforward solution for me is to have some helper like:

{{#l20n `Hello ${username} bla bla bla ${author}` username author}}

This should work on templates side. But I’m stucked in understanding how I should get strings to use and where to store them…and how to use them in can-component :slight_smile: Previously we used some custom JSP tags that just render correct strings into HTML that servlet returns us (it returns HTML not JSON). So we had no issues with translations because it was done on server-side.

What I think might work is to have some ajax servlet that returns me JSON object that contains map with key - value pairs. After I put response to can-component's viewModel in order to have an access there and pass values to helper above. If I have multiple instances of components on the same page I also should implement some client-side translations storage in order to check this store before making request maybe we already requested this prop.

But such approach looks quite complicated and I have to put translated strings into components view model which seems incorrect to me. Because this isn’t data, this is text.

For example I need to support translations here:

<super-input placeholder="Congratulate this person ..." limit="500"></super-input>
<button can-click="addComment">Add Comment</button>

or here:

<div class="commentList" style="height: {{expanderHeight}}px">
    {{#each comments}}
        <comment-item comment="{.}" is-userpic-enabled="{{isUserpicEnabled}}" is-profile-enabled="{{isProfileEnabled}}"></comment-item>
    {{/each}}
</div>
{{#moreThanShowLimit}}
    <div class="commentList-actionPanel">
        <button class="a-btn a-btn--secondary" can-click="{toggleExpander}">
            <span class="a-btn-text">{{#isCollapsed}}View All Congratulations{{else}}Hide All Congratulations{{/isCollapsed}}</span>
        </button>
    </div>
{{/moreThanShowLimit}}

Maybe someone had real production experience and can help me with this ?

Normally, for localization I’ve just used a JS / JSON file that contains the key/value pairs of English values -> translated values.

If you’re using steal, you can then use steal-conditional to conditionally load only the translation file you need: http://stealjs.com/docs/StealJS.guides.substitution_conditional_loading.html

Are you saying that it’s not possible for you to create the list of translations up front and you need to be able to dynamically load them from the server?

I think the main problem is that we don’t have single page application this is multli-page Java app, that can contain some can.js pieces. Some component. So we don’t have Steal or something. And I can’t get all translations for the whole application at once, because its huge, with lots of functionality that can be disabled / enabled for different clients.
All translation props are in a database.

So I was thinking about creating some class like ‘translationManager’ that should scan new page and check if any can.js component presented. Maybe some special data-attribute with component key. After that it collects keys remove duplicates (if we have several instances of the same components) and send this to the server and in the response we can have JSON with key - value pairs.

The issue that I can see right now is what if some component appears dynamically and translationManager can’t “see” it on initial page load.

And another question even in this example that you mentioned above, how you “insert” correct translations into components ?

Hi,

I haven’t read your question in detail so maybe my case will not apply. I have been using http://i18next.com/ for quite a while. I created a localisation class to deal with the actual translations:

Here’s an example of how it would be used in a view:

https://github.com/Shuttle/Shuttle.Sentinel/blob/master/Shuttle.Sentinel.Site/src/user/login/login.stache

And then, following down the components, the label is implemented like so:

https://github.com/Shuttle/Shuttle.Sentinel/blob/master/Shuttle.Sentinel.Site/src/components/label.js

I’m currently upgrading this code to v3.0 from another codebase that was already in development so it isn’t nearly complete but the localisation works OK. Some of my localisation files are here:

Thank you for the example.
I think I get the main idea. Most of projects store translations in file system in some .json files. In my case I have a database, but I think I can deal with this and store it in a similar way.
And I already implemented similar component that returns translated values.

It is quite possible to have an API of sorts (web-api/rest) that provides the translations from your database in a json format or export them to the json files.