All Tutorials

Translation keys and the t filter

All Tutorials

Translation keys and the t filter

Translation keys and the t filter

You can access translated content in your internationalized Shopify theme by using translation keys and the t (translation) filter in your template files.

This tutorial shows how to use translation keys and the t filter to access the locale file for the active language and return the corresponding string of translated text in the locale file.

Retrieve a translated string

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.

Translation key

The following example shows how to output a string from a locale file to a Liquid template, section, or snippet file. In this case, the translation key is being used to output "Your email" within the comments section on a store's blog.

The translation key must be wrapped in single quotes:

Input

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

Locale files

Let's assume your theme is offered in English, French, and Spanish. The following examples show how to include a corresponding translation key for 'blog.comment.email' in each of the applicable locale files:

locales/en.default.json

Input (English)

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

locales/fr.json

Input (French)

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

locales/es-ES.json

Input (Spanish)

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

HTML

The following examples show the returned HTML for the three locale files:

Output (English)

<span>Your email</span>

Output (French)

<span>Votre adresse courriel</span>

Output (Spanish)

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

Interpolate 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>

Pass 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

Escape 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>

Include 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 }});

Pluralize translation keys

Passing count to the t filter allows for locale-aware pluralization.

For example, English has the two pluralization forms:

  • one: aka. "singular". ex. "I have 1 car"
  • other: aka. "plural". ex. "I have 4 cars"

Other languages have more or fewer pluralization forms, and have different rules for when to use each form.

Supported pluralization keys are defined by the Unicode Consortium's CLDR and are:

  • few
  • many
  • one
  • other
  • two
  • zero.

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": {
        "one": "You've made {{ count }} order with us",
        "other": "You've made {{ count }} orders with us"
      }
    }
  }
}

Returned code

// count = 1
<h1>You've made 1 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.

Include template elements in 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 }}