• Documentation
  • Transifex Live
  • Technical Instructions

Technical Instructions

In this article, we'll explain how Transifex Live works behind the scenes. If you're a developer, we've also included some instructions on how you can customize the behavior of Transifex Live.

How a user's language is detected

The window.liveSettings.detectlang field of the JavaScript code can be used to get the user's preferred language. When this option is set to true, Transifex Live tries to guess the language in the order listed here:

  • Look for a ?lang=code URL parameter, e.g. www.transifex.com/?lang=de.
  • Match code.domain.xyz domain, e.g. de.transifex.com.
  • Look for domain.xyz/code/ URL pattern, e.g. www.transifex.com/de/features.
  • Check the browser's language preference.

For more customization options, check out the Transifex Live JavaScript API documentation.

Hiding translation swapping on page load

Although translations are cached locally to the user's computer, when a user fetches translations from the Transifex CDN for the first time, they might see a page in the source language briefly before the translated language appears.

To avoid this, add a special txlive class to the <body> of your page (be sure that you still install the JavaScript code inside the head). Like this:

<head>
...JavaScript integration code...
</head>
<body class="txlive">
...
</body>

The txlive class hides the underlying content; it's removed when the translation has been applied to the page.

Creating a custom language selector

Each website has its own way of presenting a language selector to the user. The snippet below is an example of how you can create a custom language selector using the JavaScript API.

//This is called each time the languages list is retrieved
//from Transifex Live. This may happen more than once so we should
//be able to handle this case.
Transifex.live.onFetchLanguages(function(languages) {

    //set the language selector to the source language (default)
    $('#language-current').html(
        Transifex.live.getSourceLanguage().name
    );

    //empty our language list
    $('#language-selector').empty();

    //add translation languages to the list
    for (var i = 0; i < languages.length; ++i) {
        $('#language-selector').append(
            '<li data-code="' + languages[i].code +
            '" data-name="' + languages[i].name +
            '">' + languages[i].name + '</li>'
        );
    }

    //handle user selecting a language
    $('#language-selector').find('li').click(function(e) {
        e && e.preventDefault();
        var code = $(this).closest('[data-code]').data('code');
        var name = $(this).closest('[data-code]').data('name');

        //tell transifex live to translate the page
        //based on user selection
        Transifex.live.translateTo(code, true);
    });

    //called when Transifex Live successfully translates the
    //page to a language. In that case lets update the
    //selected language of the widget
    Transifex.live.onTranslatePage(function(language_code) {
        $('#language-current').html(
            Transifex.live.getLanguageName(language_code)
        );
    });
});

Customizing your website per language

There might be cases where a web page must be customized based on the selected language. In that case there are two options.

The first one is to use CSS. Transifex Live alters the <html lang> attribute, so special CSS directives can be used. For example:

html[lang="ar"] .foo { … }
html[lang="de"] .foo { … }

The second option is to use the Transifex Live JavaScript API and capture the event:

Transifex.live.onTranslatePage(function(lang) {
    if (lang === ‘ar') {
        //do stuff
    }
});

Handling dynamic content

By default, Transifex Live automatically handles static content, i.e. HTML that's initially loaded from the first HTTP request. However, many websites have dynamic content that must be translated too, such as popups or content loaded from AJAX calls.

Dynamic content is handled automatically when the "Enable translation of dynamically injected content" check is enabled in the Live Settings (enabled by default), however, the developer can also handle it manually as well.

This solution involves using Transifex Live JavaScript API to manually mark content for translation by specifying the HTML DOM node/nodes to be translated.

Here is an example of how to translate a dynamic portion of a page:

...
//start adding dynamic content after Transifex Live
//has loaded and translations have beed fetched
Transifex.live.onReady(function() {
    ...
    //Add dynamic parts of the page
    $('#foo').append(
        '<h1>Section</h1><p>This is a paragraph</p>'
    );
    Transifex.live.translateNode($('#foo').get(0));
    ...
});

Another technique is to use the Transifex.live.translateText call inside a JavaScript template engine. The following example shows how this can be done using underscore.js.

//after the inclusion of live.js library
<script type="text/javascript">
    //create an alias
    window._t = Transifex.live.translateText;
</script>
...
...
<script type="text/template" id="template">
    <div>
        <h1><%= _t("This is a title") %></h1>
        <p><%= _t("This is a paragraph") %></p>
        <p><%= _t("Hello {name}", params) %></p>
    </div>
</script>
...
...
<script type="text/javascript">
    ...
    $('#foo').html(
        _.template($(#template).html())({
            params: {
                name: 'John'
            }
        });
    );
</script>

How the Transifex Live JS parser works

The Transifex Live JavaScript parser works in the background for you. As you and your users browse through pages of your live website (or pages in a staging environment), Live automatically detects translatable content in the background and stores them for your review.

This is how your content is segmented:

Block tags

Example of block tags are: DIV, P, H1, TABLE, UL, OL etc.

When the content of a block tag is a combination of plain text and inline elements such as SPAN, all the content is considered a single segment.

HTML:
  <div>
    <p>This is a paragraph</p>
    <p>This is a paragraph with <span>inline element</span></p>
  <div>

Segments:
  "This is a paragraph"
  "This is a paragraph with <span>inline element</span>"

Plain text

When the content of a block tag is NOT a combination of plain text and a tag, only the plain text content is extracted.

HTML:
  <div>
    <p>
      <span>My span text</span>
      <span>Another span text</span>
    </p>
  </div>

Segments:
  "My span text"
  "Another span text"

Page title

HTML:
  <title>My title</title>

Segments:
  "My title"

Anchor titles

HTML:
  <a title="My title">..</a>

Segments:
  "My title"

Image titles and alt text

HTML:
  <img title="My title" alt="My alt text"/>

Segments:
  "My title"
  "My alt text"

Input values and placeholders

Input values are only detected for inputs with type button, reset, submit.

Textarea placeholders

HTML:
  <textarea placeholder="My placeholder text">

Segments:
  "My placeholder text"

Meta keywords and descriptions

HTML:
  <meta name="keywords" content="tag1, tag2, tag3">
  <meta name="description" content="My page description">

Segments:
  "tag1, tag2, tag3"
  "My page description"

Elements that are ignored: script, style, link, iframe, noscript, canvas, svg, audio, video, code.

Social widgets such as Facebook and Twitter that have tags with class names facebook_container and twitter_container are also ignored.

How to handle non-translatable content

You can manually define a block or node as non-translatable by adding a notranslate class.

For example:

<div class="notranslate">This content will not be translated</div>

Marking attributes for collection and translation

Apart from the attributes that are automatically detected for translations, you can define custom attributes for translation using the tx-attrs="attr1, attr2,..." attribute.

Before:

HTML:
  <span title="My title" data-content="My data content">

Segments: Nothing detected

After:

HTML:
  <span title="My title" data-content="My data"
        tx-attrs="title, data-content">

Segments:
  "My title"
  "My data"

How to tag strings in the source language

You can automatically tag source strings by using the tx-tags="tag1, tag2,..." attribute.

These tags propagate to child elements as well.

For example:

<div tx-tags="marketing">...</div>

Tags will appear in Transifex's Web Editor in all languages and you will be able to filter strings using the tags.

How to handle inline block variables

To define variables or placeholders within a block that shouldn't be translated, use class="notranslate" in the variable nodes or encapsulate them inside var tags.

For example:

HTML:
  Hi, you are visitor <span class="notranslate">142</span>
  Hi, you are visitor <var>341</var>

Segments:
  "Hi, you are visitor {{0}}"

How to handle URLs as translatable content

When images <img> or links <a> appear within a segment, their URLs are handled by default as non-translatable content (i.e variables).

Translating images

To translate an image you should treat its URL as translatable text. To do so, use the special directive tx-content="translate_urls" to enable this functionality for a node and its children.

Before:

HTML:
  <div>
    <img src="/uploads/smiley.jpg" alt="Smiley face" width="42" height="42">
  </div>

Segments:
  "<img src="{{0}}" alt="Smiley face" width="42" height="42">"

After:

HTML:
  <div tx-content="translate_urls">
    <img src="/uploads/smiley.jpg" alt="Smiley face" width="42" height="42">
  </div>

Segments:
  "<img src="/uploads/smiley.jpg" alt="Smiley face" width="42" height="42">"

Translating links

To translate a link you should treat each URL as translatable text. To do so, use the special directive tx-content="translate_urls" to enable this functionality for a node and its children.

Before:

HTML:
  <div>
    Click to go to the <a href="/features">features</a> page
  </div>

Segments:
  "Click to go to the <a href="{{0}}">features</a> page"

After:

HTML:
  <div tx-content="translate_urls">
    Click to go to the <a href="/features">features</a> page
  </div>

Segments:
  "Click to go to the <a href="/features">features</a> page"

Tip

To treat ALL URLs as translatable content within a page, add the tx-content="translate_urls" to the tag.

How to fine tune translatable content

For even finer control over how strings are detected, use the tx-content HTML attribute, which can contain the following values:

  • exclude to mark a node and its children to be excluded from string detection
  • include to mark a node and its children within a exclude block to be included in string detection
  • block to mark a node and its children to be detected as a single string
  • notranslate_urls to mark a node and its children to handle URLs as variables (default)
  • translate_urls to mark a node and its children that URLs should be translated

Include/exclude example.

Before:

HTML:
  <div>
    <p>First text</p>
    <p>Second text</p>
    <p>Third text</p>
  </div>

Segments:
  "First text"
  "Second text"
  "Third text"

After:

HTML:
  <div tx-content="exclude">
    <p>First text</p>
    <p tx-content="include">Second text</p>
    <p>Third text</p>
  </div>

Segments:
  "Second text"

Block example.

Before:

HTML:
  <div>
    <h1>A header</h1>
    <p>A paragraph</p>
  </div>

Segments:
  "A header"
  "A paragraph"

After:

HTML:
  <div tx-content="block">
    <h1>A header</h1>
    <p>A paragraph</p>
  </div>

Segments:
  "<h1>A header</h1><p>A paragraph</p>"

Localizing numbers and currencies

Transifex Live supports localized formatting of numbers and currencies. For example, when a number is presented to a German visitor it will be formatted with comma as the decimal marker and points as thousand markers, the same number when presented to an english visitor will use the reverse notation.

Furthermore, Live also handles the formatting of prices with respect to the currency position defined for each language.

In order to activate this feature you will need to mark the HTML tags you want to localize by including a tx-content attribute in your markup.

For example.

Before:

<div>
    <p>1.000.000.000,45</p>
    <p>125.4km</p>
</div>

After:

<div>
    <p tx-content="number">1.000.000.000,45</p>
    <p tx-content="number">125.4km</p>
</div>

The above example will work only if the format of the number matches that of the selected source language. For example, if you have english as a source language then a number like 1,123,456.50 will not be localized except if you provide an explicit definition of the format by adding a tx-format attribute.

Markup example with explicit format definition.

<div>
    <p tx-content="number">1,123,456.45</p>  <-- Will not work with en locale
    <p tx-content="number" tx-format=",.">1,123,456.45</p> <-- Will work because of explicit format
</div>

All the above will also work for nodes holding currency values.

<div>
    <p tx-content="currency">5.123,50€</p>  
</div>

The above currency value will be presented as € 5,123.50 to a US visitor and € 5 123,50 to a French one.