At the moment I'm converting a website from a different CMS to Craft v3. The 'old' CMS had a convenient way to set a hierarchy for static translations in yaml files so that we could split translations into groups per section on the website.

Like this:

    PrevPage: 'Previous'
    NextPage: 'Next'
    GotoPrevPage: "Goto previous page: '{prevPageTitle}'"

Now I can't find anything like that on the documentation and google search on Craft CMS. At the moment this is what I got instead:


return array(
    'PageNavigation.PrevPage' => 'Previous',
    'PageNavigation.NextPage'=> 'Next'
    'PageNavigation.GotoPrevPage' => "Goto previous page: '{prevPageTitle}'"

So every translation-item has a group supplied to it as a prefix, followed by a dot and then the translation-itemID. But this gets ugly soon and is not as convinient as what I was used to in the other CMS.

1) Does anybody here perhaps knows if CraftCMS has a better way of setting hierarchy to static translations? So to group translation items to sections/elements on the website?

2) Is there a way in Craft CMS to have a placeholder inside the translation-string being replaced by a variable inside the template?

In the 'old' CMS I could replace a placeholder like {placeholder} inside a translation-string by a dynamic variable inside the template. So a translation string like "Goto previous page: '{prevPageTitle}'" would come out as "Goto previous page: 'all about craft blog title'". Is there some functionality build in Craft that could replace a placeholder in the translation-string by a dynamic string?

Thanks in advance!!


You can include custom translation categories within your config/app.php

return [
    'modules' => [
        'my-module' => \modules\Module::class,
    'components'    => [
        'i18n' => [
            'translations' => [
                'foo'  => [
                    'class'            => \craft\i18n\PhpMessageSource::class,
                    'forceTranslation' => true,
                    'basePath'         => '@translations',
    //'bootstrap' => ['my-module'],

This will include the custom group foo to your app, make sure to change the basePath variable to a path you like

That being said your folder structure will look like

-your base path
|-- en-US
|-----> foo.php
|-- de-DE
|-----> foo.php

within these files you can create your custom translations

return [
    'foo' => 'bar'

{{ 'foo'|t('foo') }} -> will now display bar
{{ 'foo'|t('site') }} -> will still show foo
  • I was actually hoping for something to be possible inside the translation-files themselves. Like creating arrays as groups with sub-arrays as sub-groups, or something like that. The sections I'd like to keep grouped don't have many different keys and are for small parts of the website instead of different (big) components. So this seem to be a little overkill for this purpose. That said; very good to know this is possible though and thanks a lot for your detailed and clear explanation on this. Don't know about loadtimes, but being able to do this in the config looks very flexible! Thanks – Friksel Jul 19 '18 at 6:42
  • According to your answer it looks to me you're very informed about the matter in Craft. And there's no answer telling this can be done from inside the translationfiles themselves. Next to this there's no reaction on the second part of my question about the possibility to add placeholders to the translation-strings to dynamically insert strings inside the template during a translationcall, so I guess that's not possible in Craft (yet?). So I mark your answer as the right answer. – Friksel Jul 19 '18 at 6:47
  • 1
    Oh sorry I forgot to answer about the 2nd part... It is possible to include placeholders you can do that via {{ 'go to page {title}'|t('site', {title: entry.title} }} just add an object as your 2nd parameter. They keys must match with the words inside { } and those values will replace them. – Robin Schambach Jul 19 '18 at 7:14
  • Cool @RobinSchambach ! Thanks a lot for this addition. I'll definitely gonna use that one! :) – Friksel Jul 19 '18 at 18:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.