Services
Internationalization
Translation files
Translations are JSON files, one per language and domain (a domain groups the texts of one area: common, errors, validation, admin, menu, api, messages…).
config/locales/
├── es/common.json
├── es/errors.json
├── en/common.json
└── pt/common.json
plugins/<plugin>/config/locales/es/<domain>.json a plugin's translations
{
"save": "Save",
"record_not_found": "{type} not found",
"user": {
"greeting": "Hello, {name}"
}
}
Keys are relative to the file and use dots for nesting: in the common domain, user.greeting is "Hello, {name}". {parameters} are replaced when translating.
Translating in PHP
__('save'); // common domain
__('user.greeting', ['name' => 'Ana']); // "Hello, Ana"
__('record_not_found', ['type' => 'Product'], 'errors');
__('main', [], 'menu', 'noticias'); // a plugin's translation
__d('errors', 'not_found'); // shortcut with the domain first
__n('item', 'items', $count); // singular / plural
I18n::translate('save'); // the long form
If the key does not exist in the current language, it is looked up in the default language. If it is still missing, the key itself is returned (with returnKeyOnMissing) and, with logMissingKeys, it is logged.
Translating in templates
{t key='save'}
{t key='user.greeting' name=$usuario->usr_nombre}
{t key='not_found' domain='errors'}
{t key='main' domain='menu' plugin='noticias'}
{t key='save' assign='buttonText'} {* stores it in $buttonText *}
{trans domain='validation'}required_field{/trans}
{'save'|t}
Current language
The controller sets the language when it is constructed, with this priority:
- The request's
apiParameterNameparameter (default?language=en), for that request only. - The value stored in the session under
sessionKey(defaultLanguage.abbreviature). defaultLanguage.
I18n::getLanguage(); // 'en'
I18n::setLanguage('pt'); // only if it is in availableLanguages
I18n::getAvailableLanguages();
// Remember the user's choice
$this->Session->write('Language.abbreviature', 'en');
Configuration
config/i18n.php (can be overridden per domain):
| Key | Purpose |
|---|---|
defaultLanguage, fallbackLanguage |
Default and fallback language. |
availableLanguages |
Allowed languages, for example ['es', 'en', 'pt']. |
autoload, autoloadDomains |
Domains loaded at start-up (by default common and errors). The rest are loaded on first use. |
autoloadPlugins |
Look for translations in the active plugins. |
cache |
Keep the parsed JSON files in the i18n cache. |
logMissingKeys, returnKeyOnMissing |
What to do with missing keys. |
apiParameterName, sessionKey |
Language parameter and session key. |
pluralRules |
Plural rule per language (a function that receives the count). |
Translations in JavaScript
The admin panel exposes translations to the browser through Admin/Js/I18nController (/admin/js/i18n.js), for use in the panel's scripts.
Translatable content
For database records translated into several languages (category names, news…), models use TTranslatableTrait: each translation is another record with idi_codigo and a reference to the main record. See Models.