Theme Language Packs

Theme language packs are JSON files located in the ~/theme/lang directory to improve international support for Theme developers. Language pack filenames follow our Translation Code structures (all lowercase) and may be a language code only (e.g. en.json) to represent the international version of a language, or both language and country code (e.g. en-gb.json) representing a regional translation.

Language Pack support is embedded into the EVML String object and some <ev:tags>. They’re designed to be used to translate regions of a Theme outside of <ev:editable>or <ev:translate> tags, or in conjunction with <lang> tags.

How it works

Translations are performed on a translation reference - a string which looks a bit like JavaScript dot notation. You’re free to define your own JSON structure, so we can make up any translation reference so long as it follows a few rules:

  • Use alpha-numeric characters a-z and 0-9, underscores _ and dashes - in your references.
  • Use dots . to structure your JSON.

A common example might be the desire to translate next and previous buttons on pagination. So we might want a translation reference like pagination.next and pagination.previous.

Your ~/theme/lang/en.json structure would therefore look like:

{
  "pagination": {
    "next": "Next page",
    "previous": "Previous page"
  }
}

The path supports any depth of notation including array notation. For example, the following is a perfectly legitimate path, albeit not particularly desirable:

{{ 'page.home.titles[1]'.t }}

Results in "My title 2" if your language pack JSON looked like:

{
  "page": {
    "home": {
      "titles": [
        "My title 1",
        "My title 2"
      ]
    }
  }
}

Default language

The default language for Themes will be assumed to be en (the Application default), unless defined within the ~/theme/config/theme.json file.

{
  ...
  "defaults": {
    "lang": "en"
  }
}

Usage with EVML String

EVML String now includes a String.translate() method and a String.t() alias, which means we can do things like:

{{ 'pagination.next'.translate() }}

or

{{ 'pagination.next'.translate }}

or even

{{ 'pagination.next'.t }}

String templates

Values support replacement variables. These look a lot like EVML output tags, but they’re more primitive and do not have access to EVML in any way.

Consider a JSON file:

{
  "greeting": "Hello {{ name }}"
}

In our EVML template we may welcome a current user:

{{ 'greeting'.t({ name: 'Geoff' }) }}

Would result in:

Hello Geoff

Pluralisation

Language packs support the full spectrum of pluralisation permitted by Evance and the pluralize property/variable is reserved specifically for cardinal or ordinal pluralisation.

Properties permitted are language dependent:

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

In English we typically use just one and other for cardinal values (e.g. 1 car, 2 cars). Arabic however uses the full spectrum.

Consider cardinal units:

{
  "units": {
    "month": {
      "one": "{{ pluralize }} month",
      "other": "{{ pluralize }} months"
    }
  }
}

May be used as:

{{ 'units.month'.t({ pluralize: 2 }) }}

Would result in:

2 months

Ordinal values are also supported. For example in English we may want to have placements:

{
  "position": {
      "one": "{{ pluralize }}st place",
      "two": "{{ pluralize }}nd place",
      "few": "{{ pluralize }}rd place",
      "other": "{{ pluralize }}th place"
  }
}

May be used as:

{{ 'position'.t({
  pluralize: 21,
  isOrdinal: true
}) }}

Would result in:

21st place

Nesting translations

It is possible to nest translations. Consider the following phrase:

Just 3 days until Black Friday.

This could be converted into:

Just {{ days }} until Black Friday.

This could end up looking something like this:

{{ 'black-friday-countdown'.t({
    days: 'units.day'.t({ 
      pluralize: 3 
    })
}) }}

With our JSON file looking like:

{
  "black-friday-countdown": "Just {{ days }} until Black Friday.",
  "units": {
    "day": {
      "one": "{{ pluralize }} day",
      "other": "{{ pluralize }} days"
    }
  }
}