Thanks to the Base/Lang module, epesi supports translating words and phrases into any language. In this context, translation covers more than changing language — it also includes tweaking wording for look and feel, such as shortening an overly long label.
Translations are global, and only a super administrator can change them, through Language & Translations in the Administrator menu. Within the current language, translations can be used purely to tweak look and feel. To switch epesi's language entirely, use a language pack — a file containing a full set of translations. Language packs ship with the default epesi package.
The translation mechanism is simple: wrap any label in one function, and it becomes something users can change later.
__($text)
The argument should always be a string — the original label, in English. For example, to create a label reading Click here to view next entry:
$label = __('Click here to view next entry');
$label now holds a string that will change depending on the user's selected language, once a translation is provided.
You can also include placeholders in a translated string. If a label has a varying part in the middle, use placeholders so the whole label stays a single translatable phrase. For example:
$label = __('This is the %d entry out of %d', array($number, $count));
Placeholders follow printf() format.
Two other methods, alongside __(), exist specifically to support the automated tool that scans the codebase for translatable strings:
_V() - translate variable. Use this when the string being translated isn't written out explicitly at the call site.
_M() - mark for translation. This doesn't translate anything — its return value is exactly the same as vsprintf() — but it marks the string so the scanning tool can catch it, for cases where the call itself must pass the original (English) string.
A module built on RecordBrowser makes the distinction clearest. When you install a RecordSet, the field names should eventually be translated for the end user — but only when they're displayed, not at install time, since installation saves the field names into the database and the code later references those exact English names. The problem is that outside the installation routine, these strings rarely appear anywhere else in the code, leaving the scanning tool nothing to catch. That's why _M() is called on each field name during installation: it marks the string for translation without actually translating it, so the English name is what gets stored and referenced later.
When RecordBrowser later displays these names, it needs to translate them — and by then, the field name is held in a variable, not written out as a literal string. Calling __() on a variable would give the scanning tool nothing useful to find; it would just see $label or some other variable name. To catch this, epesi raises a warning whenever __() is called with a variable instead of a literal string, prompting the developer to make sure every possible source of that variable is wrapped in _M() instead.
_M() is most commonly used in installation routines (CommonData, RecordBrowser) and menu item definitions. Avoid _V() where possible.
Notice: the script that scans code for translatable strings isn't publicly available yet. It may be released at a later date.