Language and Translation Hooks

1 views Markdown

The seven hooks over text: resolving a translation, saving one, sweeping a pack, and adding, removing or configuring a language.

Overview

Text travels two ways: a key resolves and reaches the screen, or a translation is saved and reaches the disk. Each end carries a filter.

Beside them sit the events of the pack itself: opening one, deleting one, changing its settings. A new pack is not born empty; it is copied from an existing language.

Reference

Changing a resolved text

filteri18n.translation
Language::g passed by link

Runs after a translation key resolves to text. Every piece of text in the system passes here: it is a hot path, so keep it light.

Parameters 3
$valuestringby linkThe resolved text. What you write over it is the result.
$keystringThe key that was asked for.
$langstringThe language used to resolve it.
Return 1
voidThe return is ignored; you write over the text. Leave it alone and the original comes back.
Listener
Hook::add('filter:i18n.translation', 10, function (&$value, $key, $lang) {
    // Every text passes here: sift on the key first.
    if ($key !== 'website/home/title') return;

    $value = Acme::brandedTitle($lang);
});

Adjusting translations before they are saved

filteri18n.translation_save
AdminLanguages passed by link

Runs before translations are written to disk. The array you hold is what gets written.

Parameters 2
$valuesarrayby linkKey against value. A value may be plain text or an array carrying content and variables: be ready for both.
$idstringThe target language.
Return 1
voidThe return is ignored; you write over the array.
Listener
Hook::add('filter:i18n.translation_save', 10, function (&$values, $id) {
    // A value may be plain text or an array.
    foreach ($values as $k => $v)
        if (is_string($v)) $values[$k] = trim($v);
});

Following a translation being saved

actioni18n.translation_saved
AdminLanguages only what truly changed

Runs after a translation key is saved.

Parameters 2
$keystringThe full key that was saved.
$savedarrayThe languages actually written to disk. Languages sent but unchanged are absent from this list: it does not answer "which languages were submitted".
Return 1
voidThe return is ignored.
Listener
Hook::add('action:i18n.translation_saved', 10, function ($key, $saved) {
    // The list holds what CHANGED, not what was submitted.
    foreach ($saved as $lang) Acme::invalidateCache($lang, $key);
});

Following a bulk replacement

actioni18n.bulk_replaced
AdminLanguages one language pack

Runs after a word is replaced throughout one language pack.

Parameters 4
$langstringThe single language the sweep ran on.
$wordstringThe raw word searched for; it is not a pattern.
$replacementstringThe text written in its place. It is not read as a back-reference: what it holds is written literally.
$changedintHow many keys actually changed, not how many were selected.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:i18n.bulk_replaced', 10, function ($lang, $word, $replacement, $changed) {
    // The counter holds what changed, not what was selected.
    Acme::auditSweep($lang, $word, $changed);
});

Following a language being added

actionlanguage.added
AdminLanguages opened as a copy

Runs after a new language pack is opened. The pack does not start empty: it is built as a copy of an existing one.

Parameters 2
$keystringThe key of the new language.
$copied_fromstringThe language the content was copied from. The new pack starts full of the source texts: it does not look "untranslated", it looks wrong-languaged.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:language.added', 10, function ($key, $copied_from) {
    // The pack starts full of the source texts: put it in the translation queue.
    Acme::queueTranslation($key, $copied_from);
});

Following a language being deleted

actionlanguage.deleted
AdminLanguages after deletion

Runs after a language pack is deleted.

Parameters 1
$keystringThe key of the deleted language.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:language.deleted', 10, function ($key) {
    Acme::dropTranslations($key);
});

Following language settings changing

actionlanguage.settings_updated
AdminLanguages after the write

Runs after the settings of a language are saved.

Parameters 2
$idstringThe key of the language updated.
$packagearrayThe settings written: display name, rank, whether it reads right to left, and status.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:language.settings_updated', 10, function ($id, $package) {
    Acme::syncLocale($id, $package);
});

Pitfalls

The translation filter is a hot path

Every piece of text passes through it, hundreds of times on a single page. Sift on the key before doing anything heavy, and leave straight away for calls you do not care about.

The saved list is not the submitted list

The list carried by the translation save event holds only the languages whose value actually changed. Languages submitted unchanged are absent, so do not answer "which languages were sent" from it.

Was this helpful?

Thanks for your feedback!

Still Need Help?

Our support team is here around the clock for anything you can't find above.