Back to How-Tos

Single-Script Translation and Replace

We often talk about optimization and how it affects output production times. This how-to will show you a relatively advanced, but very powerful way, of optimizing an arbitrary number of field replacements in your template using a single script. Not only that, this script also automatically supports Localizing data, and some basic text transformation functions.

As we've seen in a few places, including Optimizing Scripts in the documentation and Connect with Evie - Using Selectors in Scripts and CSS, it's much more efficient to replace data on your page using class selectors, rather than relying on the default @placeholder@ variables created by Connect.

This how-to does not related to dynamic table scripts, which are already optimized in this way.

Preparing your Template

There's actually very little to do to prepare your template. Let's go through it.

  • Instead of dragging your fields into the template, simply type them in with their field name. For example if you have a field named City in your data model, type in {{City}}
  • In any element where you have placeholders, apply the class named tr
  • Create a new script in the Script Pane, make the selector tr and paste from the code below in The Script section.

You should get something that looks like this: Replace and Translate, Example Element

The tr class can be applied to any element that contains text, such as td, p, h1, etc. You can also enhance performance by simply surrounding your placeholder (or a translation string, see below) with a span. Right-click any text and select Wrap in Span, then apply the tr class to that span.

Using string manipulation functions

While limited in scope, it's possible to use some very basic Javascript functions directly within the placeholders to modify the way the string displays in preview and in the output. Essentially, any Javascript String method that does not require any arguments can be added after the name of the field, separated by a pipe (|).

For example, the following works awesomely: {{LastName|toUpperCase}} will transform Ludwick in to LUDWICK in the output.

Applying Translations

This is the 2nd awesome part of this script: it supports translating strings straight out of the box. It only requires that you have a language-defining field in your data model, and that you create your JSON files containing translation strings.

What's the 1st awesome part of this script, you ask? A significant improvement over using separate, default @placeholder@ scripts. How significant depends on how many fields you have in your template!

The translation can be applied not just to the placeholders themselves, but to any text around it within the same element. For instance, look at the screenshot above: the paragraph contains actual text City of: {{City}} within the paragraph.

For the translation matrix itself, you'll need one JSON file per language, where each key is the string you have in your element, and the value is the translated string. For example:

  • Right click the Snippets folder in the Resources Pane
  • Select New JSON Snippet
  • Give it a name such as fr_FR.json
  • Enter the contents below:
{
	"City of: {{City}}": "Ville de: {{City}}"
}

Save, and make sure the languageCode variable is set to a field in your data model, for instance:

var languageCode = record.fields.Language;

The Script

Remember the Selector for this script should be td !

var languageCode = 'en_US';

var dict = {};
try {
	dict = loadjson('snippets/' + languageCode + '.json');
} catch(e) {
	dict = {};
}

var exprRegex = /{{\s?(.+?)\s?}}/;
var delimRegex = /(\.|\|)/;

var parseExpr = function(expr) {
	var tokens = expr.split(delimRegex);
	var value = record.fields[tokens.shift()];
	var op = null;
	tokens.forEach(function(tok, i) {
		switch (tok) {
			case '.':
				if (i == 0) value = JSON.parse(value);
				op = 'prop';
				return;
			case '|': 
				op = 'call';
				return;
		}
		
		if (op == 'prop') {
			value = value[tok];
		}

		if (op == 'call') {
			value = value[tok]();
		}
		
		op = null;
		return;
	});
	return value;
};

var format = function() {
	var fmt = arguments[0];
	var args = Array.prototype.slice.call(arguments, 1);
	return fmt.replace(exprRegex, function($0, $1) {
		return parseExpr($1);
	});
};

results.each(function(el) {
	var innerHTML = results[el].html();
	var key = innerHTML.trim();
	var value = dict[key];
	var newValue = value !== undefined ? format(value) : format(key);
	results[el].html(innerHTML.replace(key, newValue));
});

Download this script as an importable .OL-script file.