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
and0-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"
}
}
}