0

I'm using Knockout.js to allow the user to select which language my webapp should be displaying.

I've basically made the languages like this:

function AppViewModelNorwegian() {
this.Username = "Brukernavn";
this.Password = "Passord";
this.Rememberpassword = "Husk passord";
}
function AppViewModelEnglish() {
this.Username = "Username";
this.Password = "Password";
this.Rememberpassword = "Remember password";
}

And then I apply the language like this:

ko.applyBindings(new AppViewModelNorwegian());

It works for the first language selection, but how can I allow for changing of the language?

Using ko.applyBindings over again does not work, since I'm not allowed to apply bindings multiple times to the same element.

ko.applyBindings(new AppViewModelEnglish()); //Does not work

How should I change the binding in order to change the language?

Publicus
  • 1,550
  • 7
  • 18
  • 33

4 Answers4

2

Using knockout you can store your languages objects in an observableArray and use a computed to switch between them.

Here's a simple example :

Fiddle : http://jsfiddle.net/RapTorS/xWVw2/

var vm = function (languages) {
    var self = this;
    self.index = ko.observable(0);
    self.languages = ko.observableArray(languages);
    self.resources = ko.computed(function () {
        return self.languages()[self.index()];
    });
};
Romain B.
  • 266
  • 2
  • 5
1

Here's a simple example, but you'd maybe want to use something like i18next as your app gets more complex.

Fiddle: http://jsfiddle.net/jiggle/dZ9Em/

function AppViewModel() {
    var self = this;
    self.Username = ko.observable("Username");
    self.Password = ko.observable("Password");
    self.Rememberpassword = ko.observable("Remember Password");
    self.Language =ko.observable("english");
    self.Language.subscribe(function(lang){

          if (lang=="norwegian"){
               self.Username("Brukernavn");
               self.Password("Passord");
               self.Rememberpassword("Husk passord");
          };

          if (lang=="english"){
               self.Username("Username");
               self.Password("Password");
               self.Rememberpassword("Remember Password");

          };
    });
    self.Languagelist=['english','norwegian'];
    return self;
}

var vm = new AppViewModel();
ko.applyBindings(vm);

The code sets your language text as knockout observables, and also the current language, then we subscribe to the language observable, such that when it is updated (the user selects a different language), we check what the new value is (lang) and then set the observables to the correct words.

For more information on subcribing to observables and observables in general have a look a the knockout documentation, that has good examples:

http://knockoutjs.com/documentation/observables.html

I've captured 'this" using var self=this; at the start of the viewmodel to ensure we have a reference to the language text observables when the subcription code is called (it wouldn't work otherwise as 'this' would not be the viewmodel).

For the purposes of the demo, I've created an array of languages (just the two) and we bind this to the select dropdown to allow the language selection; the value is bound to the viewmodel's Language observable, which then triggers the code in the subscribe function to switch the language.

HTML:

<select data-bind="options: Languagelist,value:Language"></select>


<div>
    <div data-bind="text:Username"></div>
    <div data-bind="text:Password"></div>
    <div data-bind="text:Rememberpassword"></div>
</div>

Fiddle: http://jsfiddle.net/jiggle/dZ9Em/

John Lucas
  • 1,618
  • 14
  • 19
  • Thanks for a detailed answer! I also note that this only applies to the users current view - how would I apply the KO across the entire app? – Publicus Feb 21 '14 at 08:58
  • That's quite an involved question and depends on your app, is it a Single Page App (eg. using durandal, angular, etc.)? or traditional .net like webpages/forms/mvc? Search knockout+i18next on here. In particular the big answer in this question by the user 'tne' is excellent, http://stackoverflow.com/questions/16882171/durandal-knockout-app-with-multilanguage-support. At the very basic level, you could store the language selection in a cookie or local storage and each page, get that value and create the language viewModel for that particular page. I would definitely look into using i18next. – John Lucas Feb 21 '14 at 09:12
  • It's a single page app, using Kendo UI Mobile. So applying it to the current DOM would be sufficient. – Publicus Feb 21 '14 at 09:19
0

I don't think you can applyBindings again. You can use your viewModel like this,

function AppViewModel() {
    this.Username = "Username";
    this.Password = "Password";
    this.Rememberpassword = "Remember password";
    this.Language ="English";
    this.ChangeLanguage = function(languge){
         //you can add here, what you want to do after langauge change
    }
}

There are many ways, you can add a event in the binding for changing the langauge.

Pratik Bhoir
  • 2,074
  • 7
  • 19
  • 36
0

You should consider making a main model function to decide which one is pressed and based on that:

function MainViewModel() {
    var self = this;
    // Check which language is selected and then create an instance of that model such as
    self.language = ko.observable(new AppViewModelNorwegian());
    // OR
    self.language = ko.observable(new AppViewModelEnglish());
}

ko.applyBindings(new MainViewModel());

Making all the variables ko.observable() makes them update when they change automatically. Also you should consider setting your namespace properly with making sure "this" remains connected to the correct objects:

function AppViewModelNorwegian() {
    var self = this;
    self.Username = // ..... etc
}
Mike R
  • 110
  • 2
  • 10