Internationalization

Internationalization For developers

Overview

Internationalization, or i18n, is the process of extrapolating text strings in a document into individual languages, so that the document can be viewed in many different languages ​​without having to duplicate the page for each different language. Technically, internationalization refers to the process of preparing code for translation; in MODX, this process often boils down to isolating translatable strings into separate placeholders.

i18n The abbreviation i18n comes from the word “internationalization”. It means “i plus 18 letters, then n“.

MODX Revolution supports i18n at the core through something called “Lexicons”. A lexicon is simply a collection of the following data:

  • Languages ​​(IANA format)
  • Topics
  • Entries

A lexicon topic is a collection of lexicon entries. A lexicon entry is a single language string with a key and a value. Revolution splits entries into sections to speed up loading of language files, reduce loading time of the JS language cache, and make maintenance easier.

In addition, the modNamespace class is used to further separate lexicon sections into separate namespaces, preventing accidental overwriting of the main lexicon.

Locales

Some translation frameworks (such as gettext) rely on a specific locale and context to help differentiate meanings. For example, “football” has a different meaning depending on the locale (UK vs. US). MODX will likely not support locales in the core, but you can configure locales to suit your site’s organization and i18n approach. The most logical option is probably to use a plugin tied to the OnInitCulture event.

You can set the locale in the MODX system settings (or context settings if you use e.g. Babel). But make sure that the MODX system locale uses utf8 encoding (i.e. de_DE.utf8), otherwise the MODX backend will show some errors.

Lexicon Entries

A lexicon entry (or modLexiconEntry in the MODX model) is simply a single translation of a string into another language. There are a few important fields here that we’ll note:

  • name – This is the name or “key” of the entry. When using lexicons, you will reference this key.
  • value – the translation of the key.
  • topic – the topic this entry belongs to.
  • language – the IANA language key this entry is translated into.

Loading and Using Lexicons

Lexicons must be loaded first if they are to be used in the frontend. However, this is a trivial process.

Lexicons via Tag (in Contents, Chunks, Templates, etc.)

To use a lexicon entry in a tag, use the following syntax:
[[%key? &topic=`topicname` &namespace=`namespace_name` &language=`en`]]
The language, topic, and namespace properties are optional; If the tag was previously fired on the page with the same ‘topic’ property value, that topic will already be loaded. If topic is not specified, it will assume the default. If ‘namespace’ is not specified, it will assume ‘core’ or the MODX Revolution Core namespace.

It is advisable not to use the ‘language’ property for each tag if you are changing languages; this is best done via a system or context setting for the entire site or context. The best option is to have different contexts for each language. But again, MODX leaves the choice up to you.

If you have placeholders in the lexicon string, such as “This is [[+userinput]]!”, you simply specify the key (“userinput”) as the tag property and pass in the value whatever you want to replace. Example:
[[!%key? &topic=`topicname` &namespace=`namespace_name` &language=`en` &userinput=`amazing`]]
Note the exclamation mark, i.e. the prefix for the tag, this ensures that the tag will not be cached, since our string may change before the page is cached.

Lexicons in PHP

Using lexicons in your code is fairly simple; first of all, you need to make sure that the modLexicon class is loaded by instantiating it as a service:
$modx->getService('lexicon','modLexicon');
Then we want to load the topic using the load() method.

Loading Lexicon Topics with modLexicon::load()

The syntax of modLexicon::load is quite simple:
$modx->lexicon->load('topicname');
The load() function supports loading spacesva namespace. So, let’s say you had a lexicon theme named “default” in a namespace called “school”. You would load it like this:
$modx->lexicon->load('school:default');
This will load the “default” theme into the “school” namespace. If no namespace is specified, it defaults to “core”, which is the default namespace for the MODX Revolution backend.

The load() function also takes an infinite number of parameters; each parameter loads a different theme. Example:
$modx->lexicon->load('chunk','user','school:playground');
This code will load 3 themes: “chunk”, “user”, and the “playground” theme from the “school” namespace.

Additionally, the load parameter supports language-specific loading, if you want to override the default language loaded (defaults to the current value of $this->modx->cultureKey, which is set differently depending on the loaded context, and can be set via settings), you can load it like this:
$modx->lexicon->load('es:school:playground');
This will load the Spanish version of the “playground” theme for the “school” namespace. Pretty cool, huh?

Displaying Translated Content with modX::lexicon()

Now we can use lexicon() method of MODX object to get our entry with key ‘school.basketball’:
$modx->lexicon('school.basketball');
If there are placeholders in the lexicon string, like “This is [[+userinput]]!”, you can pass an array as the second argument that has key=>value pairs of the placeholder content, like this:
$modx->lexicon('school.basketball',array('sport' => 'basketball'));

Lexicons in JavaScript (inside MODX)

In the CMP, you can use the following to use lexicons _('lexicon.key').
Note that this assumes you’ve loaded the lexicon into your connector – there is no way (at least to my knowledge at this time ~Mark H.) to dynamically load other lexicon topics via JavaScript.

If you have placeholders in your lexicon string, like “This is a [[+userinput]]!”, you can pass in the placeholder values ​​as a JavaScript object, like this:
_('lexicon.key',{ userinput: 'amazing' })

Lexicons for Settings

Let’s say you’re creating system settings for a third-party component. The syntax for automatically loading them into the Revolution settings grid is simple. Let’s say we have a namespace for our component called “gallery” and a setting called “gallery.display_thumbs”

Recommended Format The recommended format for third-party component developers is to use a prefix that identifies the parent component: $*lang['name-of-component*.key-name'] = 'Your translation here.';

This helps prevent naming collisions; keep in mind that the $_lang array can contain thousands of entries, so you should ensure that each entry is unique.

To add a lexicon title and description, we would simply add the following 2 lines to our default lexicon theme for our “gallery” namespace:
$_lang['setting_gallery.display_thumbs'] = 'Display Thumbnails';
$_lang['setting_gallery.display_thumbs_desc'] = 'If true, thumbnails for the gallery will be displayed.';

And there we are!

Conclusion

Lexicons provide MODX Revolution users with many ways and options for i18n work. Lexicons consist of multiple entries per language and are grouped by topic. They can be called by PHP methods or MODX tags.

See also: modX.lexicon.

Rate article
MODX 3
Add a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.