Static Message Translations

Most websites and apps will have some UI messages that are hard-coded into the templates or PHP files. These are called “static messages”, because they aren’t being dynamically defined by content in the CMS.

If you’re building a multilingual site or app, then these messages will need to be translatable just like your CMS-driven content.

To do that, Craft employs Yii’s Message Translations feature, and pre-defines special translation categories:

  • site is used for messages that belong to the project.
  • app is used for Craft control panel messages.
  • Each plugin gets its own category as well, based on the plugin’s handle.

# Prep Your Messages

The first step is to run all of your static messages through the translator. If you’re working on a template, use the translate filter (|t). If you’re working in PHP code, use Craft::t().

{# old #}
<a href="/contact">Contact us</a>

{# new #}
<a href="/contact">{{ 'Contact us'|t }}</a>

# Provide the Translations

Once you’ve prepped a message for translations, you need to supply the actual translation.

To do that, create a new folder in your project’s base directory called translations/, and within that, create a new folder named after the target language’s ID. Within that, create a file named after the translation category you want to create massages for (site.php for project messages, app.php to overwrite Craft's control panel messages, or <plugin-handle>.php to overwrite a plugin’s messages).

For example, if you want to translate your project’s messages into German, this is what your project’s directory structure should look like:

├── config/
├── ...
└── translations/
    └── de/
        └── site.php

Now open site.php in a text editor, and have it return an array that maps the source messages to their translated messages.


return [
    'Contact us' => 'Kontaktiere uns',

Now, when Craft is processing the message translation for a German site, “Contact us” will be replaced with “Kontaktiere uns”.

# Message Parameters

Static messages can have placeholder values. For example:


return [
    'Welcome back, {name}' => 'Willkommen zurück {name}',

To replace the placeholder values with dynamic values when translating the message, pass the params argument when using the translate filter or calling Craft::t():

<a href="/contact">{{ 'Welcome back, {name}'|t(params = {
    name: currentUser.friendlyName,
}) }}</a>