i18n in Slim Framework using Symfony/Translation & Twig

I’ve been using Slim at work for the past week creating an internal web application that displays some statistics from an API, and I opted to use Twig for rendering the views since it is the templating engine I am most familiar with and in my opinion has the cleanest syntax.

The application is going to be used by multiple people and should support multiple languages, I thought that throwing an i18n(internationalization) component from Packagist was going to be a quick task, but after messing around for an hour I had figured that this might not be as easy as I initially thought.

But I finally figured out the best course of action and I thought I’d share it with all of you so that nobody else needs to reinvent the wheel or wade through piles of shitty documentation… again.

The solution I came up with involved using the Translation component from Symfony along with the a Twig extension called TranslationExtensionBridge (or some other obscurely complex name).

Either way, let’s get on with it!

I’ve put a sample application up on GitHub that you can take a look at or clone & modify.

What we first have to do is to create our composer.json file, this is what it looks like:

We’re pulling in Slim, SlimViews, Twig, Twix Extensions and Symfony translation and Symfony twig bridge.

Before we start messing with composer, we should create our file structure, You can obviously do this however you want, but for this example here is how my project is setup:

the files inside of /lang are simple PHP files that immediately return an associative array like so:

Now we’re ready to run  composer install and watch the fancy green text scroll down our terminal for awhile, when that is completed create your index.php file and pull in the composer autoloader file and use  the ridiculously long symfony namespaces, so we don’t have to type them out fully each time.


Then we create a Slim application instance.

We then have to create an instance of the Translation class like so:

What we are doing in the snippet above is creating a new Translator instance, passing it a “default” language as the first param and a MessageSelector instance as the second, what does the MessageSelector do you ask, well I have no fucking clue, it said to use it in the documentation so I did.

Anyways, we then set our fallback languages, notice that it is an array of languages and not a string, this languages will be used if the one you selected as default does not exist or does not have the translation string available.

The method   $translator->addLoader()  will setup a loader that is used to read in the language files you are going to add next with the  $translator->addResource() it should be self explanatory from the code what it does, it grabs a language file and loads it into “memory” so that we can reference strings in it later.

After we’ve done all that we have to add Twig and the Translation Bridge to the slim view ParserExtensions, you do this like so:

and you should be good to go, let’s fire up an example route!

Here is the contents of the example.twig  file:

The {{ “welcome”|trans}} strings will be replaced by the corresponding translation found in your language files.

Try it by yourself, git clone  the example application and look through the code!

If you need more documentation on twig, translation and slim framework, take a look at these pages:


  1. Thanks for the excellent tutorial and sample application. We were up and running with Slim + Twig + Symfony in very short time.

  2. Hey man, great post! I was trying to make something similar with Slim without luck, your work was really useful and worked out of the box. I will continue trying to make usable with Slim 3 following your steps. Thanks!

    1. Thanks!

      I had the same problem as you, i tried to find information on how i would do something like this in slim, but found only an overly complicated getText() based solution dealing with .po files and the like.

      Id love to check out your Slim 3 solution, be sure to notify me if you get it going :)

  3. Hello, is it possible to accomplish this without Slim ?

    I made a home made MVC php app using Twig and would like to add internationalization.

    Thanks anyway for guidelines

    1. Yes, you construct the translator object like usual but instead of adding it to the slim instance’s parserExtensions array, you add it directly to the twig instance, check the docs on Twig, I can’t remember the exact method call to do it atm.

  4. Thanks for your solution. Helped me a lot.
    I struggled at two points:
    – MessageSelector: the Translator didn’t accept it as second argument. Hence I just removed it with success.
    – How to set the locale for a route: I finally fetched it from the $_REQUEST object and set the locale directly after adding the Resources by setting the locale on the Translator.

    Do you have a better solution for the second point? (setlocale(…) didn’t work for me).

  5. Hey,
    I made it work successfully with Slim3, adapting some parts as It seems the component symfony/translation is now in version 4.

    // i18n
    $translator = new Translator(“fr_FR”);
    $translator->addLoader(‘php’, new PhpFileLoader());
    $translator->addResource(‘php’, __DIR__.’/lang/fr_FR.php’, ‘fr_FR’);
    $translator->addResource(‘php’, __DIR__.’/lang/en_GB.php’, ‘en_GB’);
    $view->addExtension(new TranslationExtension($translator));

Leave a Reply

Your email address will not be published. Required fields are marked *