Translation keys and the t filter

Hard-coded text strings in template files are not permitted in an internationalized theme. Instead, you must use translation keys and the translation filter (or t filter.)

Note

Be sure to follow our guidelines for naming and organizing your translation keys.

Translated string retrieval

The translation filter retrieves the translated content from the locale file for the active language.

When a translation key is passed in a template file:

  1. The t filter uses that key to access the locale file for the active language.

  2. The corresponding string of translated text in the locale file is returned.

Caution

You must wrap translation keys in single quotes.

For example:

theme.liquid


<span>{{ 'blog.comment.email' | t }}</span>

If your theme offers English, French, and Spanish, you need a corresponding key for 'blog.comment.email' in each of three locale files:

locales/en.default.json (English)


{
  "blog": {
    "comment": {
        "email": "Your email"
    }
  }
}

locales/fr-CA.json (Canadian French)


{
  "blog": {
    "comment": {
      "email": "Votre adresse courriel"
      }
    }
}

locales/es-ES.json (Spanish)


{
  "blog": {
    "comment": {
      "email": "Su correo electrónico"
    }
  }
}

The returned HTML for these three locale files is:

English


<span>Your email</span>

French


<span>Votre adresse courriel</span>

Spanish


<span>Su correo electrónico</span>

Note

When naming your translation descriptions, try to be descriptive and to place the translation in context. For example, article.comment_form.submit_button_text conveys more information than article.comment_form.submit.

Interpolation of template key arguments

Any arguments passed to the t filter can be interpolated, for example:

theme.liquid


{% if customer %}
    <h1>{{ 'layout.header.hello_user' | t: name: customer.first_name }}</h1>
{% endif %}

locales/en.json


{
    "layout": {
      "header": {
        "hello_user": "Hello {{ name }}!"
    }
  }
}

Returned code


<h1>Hello Jane!</h1>

Passing multiple arguments

You can pass multiple arguments to a t filter by separating them with commas:

theme.liquid

{{ 'layout.comment.metadata' | t: author: comment.author, email: comment.email  }}

locales/en.json

{
    "layout": {
      "comment": {
        "metadata": "Posted by {{ author }} — {{ email }}"
    }
  }
}

Returned code

Posted by Wilson Abercrombie — wilson.abercrombie@dayrep.com

Escaping of translated content

Translated content is escaped by default. Any HTML character is converted into its entity equivalent.

For example:

theme.liquid


{% capture link %}
  <a href="https://support.mystore.com">{{ 'layout.header.support_link' | t }}</a>
{% endcapture %}
<h1>{{ 'layout.header.welcome' | t: link: link }}</h1>

locales/en.default.json


{
  "layout": {
    "header": {
    "support_link": "support",
    "welcome": "Welcome to my store. Please contact {{ link }} should you
      need any assistance."
    }
  }
}

Returned code


<h1>Welcome to my store. Please contact <a href="https://support.mystore.com">support</a> should you need any assistance.</h1>

Including HTML in translation keys

To include HTML code in translation keys, append _html to the end of the key, for example:

theme.liquid


{% capture link %}
  <a href="https://support.mystore.com">{{ 'layout.header.support_link' | t }}</a>
{% endcapture %}
<h1>{{ 'layout.header.welcome_html' | t: link: link }}</h1>

locales/en.default.json


{
  "layout": {
    "header": {
    "support_link": "support",
    "welcome_html": "Welcome to my store. Please contact {{ link }} should
      you need any assistance."
    }
  }
}


HTML characters returned unchanged


<h1>Welcome to my store. Please contact <a href="https://support.mystore.com">support</a> should you need any assistance.</h1>

When a translation is to be used in JavaScript, whether as part of a script tag in a template file or a .js.liquid asset file, it should always use the _html suffix.

Shopify escapes all translations except those that use .html. For example, as a result of not using .html, single quotes and double quotes in a translation will end up being rendered as &#39; and &#34; when added with $.val() or alert. Shopify will escape the quotes once, and then JavaScript will escape the resulting ampersands. You'll avoid the double escaping if you use .html.


addToCartButton.val({{ 'products.product.add_to_cart_html' | t | json }});

Pluralization in translation keys

Passing count to the t filter allows custom pluralization. Supported pluralization keys are:

  • zero
  • one
  • two
  • other.

For example:

theme.liquid



{% if customer %}
<h1>{{ 'customer.orders.order_count' | t: count: customer.orders_count }}</h1>
{% endif %}

locales/en.default.json


{
  "customer": {
    "orders": {
    "order_count": {
      "zero": "Looks like you haven't made any orders yet",
      "one": "You've made one order with us",
      "other": "You've made {{ count }} orders with us"
        }
    }
  }
}

Returned code


// count = 1
<h1>You've made one order with us</h1>

// count = 12
<h1>You've made 12 orders with us</h1>

For more information about pluralization rules in different languages, take a look at the Unicode Language Plural Rules tables.

Values

Values can contain HTML and Liquid objects (through interpolation.) You should limit the presence of these elements in the translation files, to ensure a simple translation process for merchants creating an additional language.

In some cases, you might have to include template elements in the values, to accommodate linguistic and grammatical differences, for example:

English


Posted by {{author}} on {{ date }}

French


Publié le {{ date }} par {{ author }}

Want to discuss this page?

Visit the Shopify Community