The PHP framework behind SitioYa

Koshkil documentation

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:

  1. The request's apiParameterName parameter (default ?language=en), for that request only.
  2. The value stored in the session under sessionKey (default Language.abbreviature).
  3. 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.