0

I have a "locale" observable that is basically just a JS object that contains locale-specific strings. I also have a tabs observable array, which contains multiple properties, one of which is a title that is populated by a locale value.

e.g.

this.tabs = ko.observableArray([{
    title: this.locale().tabs.one
}, {
    title: this.locale().tabs.two
}]);

Here is a JSFiddle to demonstrate: http://jsfiddle.net/robgallen/v64p2/

I am trying to figure out the best strategy to get the tab titles to change when the locale observable is changed.

I have tried using knockout mapping but this doesn't seem to help. I have also tried adding a ko.observableArray.fn.refresh to update the data within the tabs array, but it simply uses the original tabs data, rather than referring back to the locale data.

4 Answers 4

1

How about this instead? updated fiddle

<ul data-bind="with: locale">
     <li data-bind="text: tabs.one"></li>
    <li data-bind="text: tabs.two"></li>
</ul>

Or this update to rwisch45's fiddle works too

Sign up to request clarification or add additional context in comments.

3 Comments

tabs is a far more complicated object than I have indicated in my example. It contains multiple properties, one of which is the localised title. My bad. I don't think I can just rewrite it from scratch.
Although I will look into calling a helper function to return a new tabs object, with the new localised values as per your 2nd fiddle.
Check out this fiddle on translations using knockout: fiddle. Maybe that will give you further ideas. :-) I suspected that your example was a simplification of your problem :-)
1

Your best bet would be to use a client-side i18n solution such as i18next. The problem with allowing a user to dynamically change the locale is that it will lead to an enormously complex UI. Text that would otherwise be boilerplate--for example, field labels, tabs, etc.--would need to be observable in order to respond to an observable change in your locale (most likely in a configuration module). That configurable observable would have to be injected into every module in order to drive the observable changes in locale.

We tried the approach you're taking and found that it weighed us down burdensomely. We opted for something unobtrusive, something that didn't require observables everywhere just for the sake of conveying a language change.

@rwisch45 suggests subscribe, which will work--and work well--for a small solution. But subscribe won't scale well.

3 Comments

Thanks for your thoughts. locale is actually an observable that i18next returns. It works fine with data-bind attributes, but not directly in another observableArray, as shown.
I too have now found out that the overhead was getting massive. I could translate the labels and any observable arrays on the fly, but I also had to refresh data from the server and set & refresh locale for any other components, e.g. momentjs, kendo. Most users will actually just login in one language, so the overhead wasn't acceptable.
@SpaceMonkey Glad I could help. Sometimes you just have to travel down a path to see where it goes :).
0

You could use subscribe (see explicitly subscribing to observables in the KO docs) to know whenever the value of the locale has changed. See updated fiddle. The following observable subscription in your view model will fire off every time that the value of locale is changed. You can put your own custom logic inside the function.

self.locale.subscribe(function(){
   alert('locale changed');
});

1 Comment

It's the custom logic I need help with, not the subscribe.
0

After thinking about the answers here, particularly Chuck's, this is about the best I could come up with:

http://jsfiddle.net/robgallen/v64p2/3/

Adding a subscription that re-populates the tabs array, using a key to lookup the changed locale string:

self.locale.subscribe(function (data) {
    var newTabs = [];
    ko.utils.arrayForEach(self.tabs(), function(tab) {
        tab.title = data.tabs[tab.key];
        newTabs.push(tab);
    });
    self.tabs(null);
    self.tabs(newTabs);
});

Not great and I realise I might not be thinking about this in the correct manner. Luckily most of the localisation is done in the html view and this works fine.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.