At autobutler.dk we are currently developing a new flow for car owners to enter. This flow is based on a data-driven API. The new flow will be a front-end client of this API.

We are using Knockout as our front-end framework.

One of the hurdles we encounted was string interpolation. We normally use Ruby and Rails for everything.

In Ruby string interpolation is easy, just "this #{var} that" will replace var with the content of the var-variable. When using it together with I18ns t method, we use %{var} instead of #{var}.

If we had a header called with <%= t('.header', var: 'MY VAR') -%> and this had a %{var} in it, we would replace it. Our prolem here is that the value of the variable isn’t known until the client gets to work.

One solution to this is to have the string split into several strings, that you can concatinate:

var s = "MY VAR";
var string = "<%= t('.header1') -%> " + s + " <%= t('.header2') -%>";

… really not a solution.

This is why we introduced the following code in our global Knockout scope:

ko.bindingHandlers.t = {
  init: function(element, valueAccessor) {
    var obj = valueAccessor() || {};
    var text = $(element).text();

    // Collect options
    var options = [];
    for(var key in obj) {
      if (key !== 'text') {
        options.push(key)
      }
    }

    // Match all properties
    var re;
    $.each(options, function(index, elem) {
      re = new RegExp("\%\{" + elem + "\}", "g");
      text = text.replace(re, obj[elem]);
    });

    $(element).html(text);
  }
};

This lets us interpolate Javsacript or Knockout variables into our strings. We can thus do the following:

<span data-bind="text: '<%= t('.header') -%>', t: { email: my_email_var }"></span>

And have %{email} in the translation replaced with the contents of my_email_var.