Obviel Template i18n

Introduction

Obviel Template has extensive internationalization (i18n) support. It lets you mark up those bits of the template that are translatable to another language. This way you can easily construct user interfaces can switch between different languages.

This document describes how to mark up translatable content in a template. To read about how to actually integrate in a translation workflow, and how to use i18n in JavaScript, read the i18n manual.

Basic i18n

We want to allow templates to be multi-lingual. To this end we need to be able to indicate which element content and which attributes are translatable.

We can do this with Obviel Template like this:

<p data-trans="">Hello world!</p>

Where trans is short for translate.

The translatable text is now:

Hello world!

and this is also used as its message id in the generated .po file.

So, an empty data-trans tells the system that the element content is translatable. You can also indicate that an attribute is translatable, by naming it in data-trans:

<a title="A title" data-trans="title"></a>

Multiple attributes can be indicated by separating them with a space:

<a title="A title" description="A description" data-trans="title description"></a>

You can also name both element content as well as attribute at the same time for translation:

<a title="A title" data-trans=". title"></a>

Here we use . to indicate the textual element content.

Variables

i18n works with {variable} notations. This:

<p data-trans="">I saw {thing}.</p>

will imply the following message id:

I saw {thing}.

And this could be translated to Dutch like this:

Ik heb {thing} gezien.

The translator simply moves the variable to that part in the text where it makes the most sense in that language.

Variables are also be re-orderable:

I saw {thing}. It was {color}.

could translate to the following Dutch:

{color} was {thing} dat ik gezien heb.

For HTML elements with simple textual content, and for any translatable content that’s in HTML attributes, we’re done with the explanations on how to mark up your template. But complexities occur when we mark up an element that contains not only text, but also HTML.

data-trans may not contain data-if and data-each

data-each and data-if may not be used on elements contained in an element with data-trans on it (when data-trans is used to indicate the content of the element as opposed to attributes).

So, the following template is illegal and will not compile:

<div data-trans=""><p data-if="foo">Blah</p></div>

data-with and data-if may however be on the same element as a data-trans attribute. In this case, they will be applied before the data-trans attribute is applied. So, this is allowed:

<p data-if="foo" data-trans="">Hello world</p>

If we’re just translating attribute content we’re fine as well:

<div title="A title" data-trans="title"><p data-if="foo">Blah</p></div>

For the sake of simplicity of implementation, data-with is also not allowed within a data-trans.

We introduce this rule because programmatic manipulation of translatable text results in very hard-to-reason about situations that are not really possible to resolve. If you need specific reasoning on how to generate translatable text, we recommend you do this inside JavaScript in the view definition.

Elements in relation to data-trans

Let’s consider the following (illegal) template:

<div data-trans="">The <em>pink</em> elephant.</div>

Why is this illegal? After all, at first glance, the translatable text could be this:

The pink elephant.

But there is a problem: we have no reliable way of finding out where in the translation the pink will move. The French translation for instance is:

L'éléphant rose.

and we’d expect a translated template to look like this:

<div>L'éléphant <em>rose</em>.</div>

Obviel Template has no way however of knowing that rose is the French for pink, and that it should it be in the em` element.

The general problem will occur with any HTML element contained within an element with data-trans on it.

In these cases, we have to help the system a bit by marking up the em element with a data-tvar:

<div data-trans="">The <em data-tvar="color">pink</em> elephant.</div>

Obviel Template will now try to translate two message ids:

The {color} elephant.

and:

pink

So, data-tvar indicates that an element is to be treated as a variable in the content indicated by data-trans.

Nested data-trans and data-tvar

data-tvar on an element implies that its content is translatable as well; it is therefore very similar in behavior to data-trans. This means a data-tvar may be nested within another data-tvar element. For example:

<div data-trans="">This is a <em data-tvar="something">complicated <a data-tvar="thing" href="">scenario</a></em>.</div>

This results in the following pieces of text marked up for translation:

This is a {something}.

complicated {thing}

scenario

data-trans may not normally be used inside a data-trans, except when it is used to mark up attributes:

<p data-trans="">Hello <em title="Hello world!" data-trans="title" data-tvar="who">{who}</em>!</p>

This combination of data-trans within data-trans is illegal however:

<p data-trans="">Hello <em title="Hello world!" data-trans="" data-tvar="who">{who}</em>!</p>

Explicit message ids

In the above examples, the system will infer the message ids in the translation files from the text in the template itself. Because in some cases this can lead to ambiguous message ids, you may sometimes want to be more explicit. You can name message ids by using a special syntax in data-trans:

<p data-trans=":hello_world">Hello world!</p>

In this case, the content of the p element will get the message id hello_world, not Hello world! as would have been the default.

The template above is the equivalent of this:

<p data-trans=".:hello_world">Hello world!</p>

You can also do this for attributes:

<a title="A title" data-trans="title:some_title"></a>

and for titles and content combined:

<a title="A title" data-trans=".:some_content title:some_title">content</a>

data-tvar implies that the content contained in an element is translatable too, so we can give it an explicit message id too:

<p data-trans="">The <em data-tvar="color:elephant_color">pink</em> elephant.</p>

Pluralization

Let’s look at this example:

<p data-trans="">{count} cows</p>

When we go about using this, we run into a problem. What if count is 1? We’d see this:

<p>1 cows</p>

But this is wrong. We want to get this:

<p>1 cow</p>

English has two plural forms, one for the singular (1 cow) and one for everything else, plural (5 cows).

We could change our template to use data-if to pick the right plural form, but that will lead to a problem when we want to i18n our template. Some languages have no plural forms, and others have more than two, and will use different rules for selecting which plural form to use based on count.

Instead we can mark up our template to indicate we want to use pluralization:

<p data-trans="" data-plural="count">{count} cow||{count} cows</p>

We have introduce a data-plural directive that indicates that we want to use the count variable to pick the correct plural form. By default in English we have two plural forms, and we define them using the || separator in a template. The singular form goes before || and the plural form goes after it.

When you run the template in the default locale, Obviel Template will pick {count} cow or {count} cows for you automatically based on count. When you run the template in another locale however what translation string is picked can be determined from count in a different way.

What if you want to translate an attribute? Let’s look at another example:

<p data-trans="title" data-plural="title:count" title="{count} cow||{count} cows"></p>

As you can see, you can use data-plural to indicate the pluralization variable for the title attribute. The rules for indicating an attribute or content work the same way as the rules for data-trans, but the value after : is held to be the name of the pluralization variable, not the message id.

The i18n manual goes into detail on how to use pluralizations.

Shortcuts: implied data-tvar

In some cases you may omit data-tvar on sub-elements in a data-trans. This can be done when the name of the data-tvar can be deduced from the variable inside the data-tvar. This template for example:

<div data-trans="">The <em data-tvar="color">{color}</em> elephant.</div>

may also be expressed like this:

<div data-trans="">The <em>{color}</em> elephant.</div>

data-tvar here deduced the variable name from the content of the em element ({color}).

You can also always omit the data-tvar in case of a data-view element:

<p data-trans="">The great <span data-view="foo"></span>.</p>

This will result in a message id like this:

The great {foo}.

Omitting data-tvar not allowed when an element contains something else than just a single variable, such as text or sub-elements. This for instance is illegal as it contains text (*) within the em element:

<div data-trans="">The <em>*{color}*</em> elephant.</div>

In this case, you need to actually mark up the data-tvar:

<div data-trans="">The <em data-tvar="color">*{color}*</em> elephant.</div>

This will result in the following two message ids to translate:

The {color} elephant

and:

*{color}*

Shortcuts: implied data-plural

When you use || within a data-trans or data-tvar element or within an attribute, you automatically imply pluralization is in use. data-plural is only necessary to indicate the pluralization variable if it cannot be determined unambiguously automatically.

So this example:

<p data-trans="" data-plural="count">{count} cow||{count} cows</p>

Can instead be written like this:

<p data-trans="">{count} cow||{count} cows</p>

because count can be unambiguously determined to be the pluralization variable, as it is the only one in use.

If you had an example like this:

<p data-trans="" data-plural="count">{count} {color} cow||{count} {color} cows</p>

you do need to specify data-plural as now there are two candidates for a pluralization variable, color and count, and we want to use count.

The same rule applies to the attribute example. We can simplify this:

<p data-trans="title" data-plural="title:count" title="{count} cow||{count} cows"></p>

To this:

<p data-trans="title" title="{count} cow||{count} cows"></p>

because the pluralization variable can be unambiguously determined.