Expose Symfony i18n messages to ExtJS

3 min read

In previous articles, I explained how to implement ExtJS in a Symfony 2 project, focusing on the Viewport and the Proxy.

Now it’s time to see one of the advantages of this marriage: expose your Symfony translation messages to your ExtJS application.

Translation file

First, create a translation file in the Resources/translations/ directory of your bundle. You can use the default domain messages or specify an other domain. In the example below, I created a file for the French:

<!-- Resources/translations/messages.fr.xliff -->
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
    <file source-language="en" datatype="plaintext" original="file.ext">
        <body>
            <trans-unit id="1">
                <source>Close</source>
                <target>Fermer</target>
            </trans-unit>
            <trans-unit id="2">
                <source>Close this window</source>
                <target>Fermer la fenêtre</target>
            </trans-unit>
        </body>
    </file>
</xliff>

Note: Symfony provides others loaders than XLIFF, including PHP and YAML.

Translations in JS

Now to expose your translations to the javascript, install the bundle JsTranslationBundle. For that, add this requirement in your composer configuration file:

"require": {
    ...
    "willdurand/js-translation-bundle": "2.0.*"
    ...
},

Then, register the bundle in app/AppKernel.php:

<?php
// app/AppKernel.php
public function registerBundles()
{
    return array(
        // ...
        new Bazinga\Bundle\JsTranslationBundle\BazingaJsTranslationBundle(),
    );
}

Protip: For more configuration, see the bundle documentation: JsTranslationBundle.

To dump the translations in javascript, run this command:

app/console bazinga:js-translation:dump

It generates the file below in js/translations:

// fr.js
(function (Translator) {
  // fr
  Translator.add("Close", "Fermer", "messages", "fr");
  Translator.add("Close this window", "Fermer la fenêtre", "messages", "fr");
})(Translator);

Then, include this file and the Translator with Assetic:

{% javascripts 'bundles/bazingajstranslation/js/translator.min.js'
'js/translations/config.js' 'js/translations/messages/*.js' ... %}
<script src="{{ asset_url }}"></script>
{% endjavascripts %}

By default, the locale is set to the value defined in the lang attribute of the html tag:

<!doctype html>
<html lang="{{ app.request.locale }}">
  ...
</html>

Now you can use the translation within ExtJS!

Let’s try with a simple dialog window:

Ext.Msg.show({
  closable: false,
  title: Translator.trans("Close", {}, "messages"),
  msg: Translator.trans("Close this window", {}, "messages"),
  buttons: Ext.Msg.OK,
  icon: Ext.Msg.INFO,
});

If the language of the user’s locale is French, it will display this message:

screenshot

ExtJS locales

Assetic has a great feature to produce different outputs for the same asset: variables. Asset variables are very useful to include ExtJS language files depending on user’s locale.

In practice, specify the possible languages for the asset variable locale:

# app/config/config.yml
assetic:
  variables:
    locale: [en, fr]

Then, include the locale file with the variable instead of the lang:

{% javascripts "/bundle/acmefoo/ext/locale/ext-lang-{locale}.js" vars=["locale"] %}
<script language="javascript" type="text/javascript" src={{ asset_url }}"></script>
{% endjavascripts %}

Thus, you can take advantage of standard translations for widgets, like the calendar for instance:

screenshot

💃 Happy Coding!

✨ Explore More:

--eof--