Frontend Translations

Frontend translations are implemented using the @becklyn/translator npm package as well as the becklyn/translations symfony bundle.

Configuration

To use translations, you need to do two things (besides writing the actual translation texts):

  1. Export all used translations
  2. Initialize your JS router

Like a lot of components, the translator supports namespaces. The reason is that we want to separate the backend translations from the frontend translations and only dump the required ones (to save on bandwidth).

Normally, you should use these namespaces:

  • app for frontend translations
  • mayd for backend translations

Exporting Translations

First you need to export all translations you want to use in JS.

To save bandwidth, only export the translations you actually use.

In your project, you export translations in the becklyn_translations.yaml config file:

becklyn_translations:
    extract:
        namespace:
            domain:
                - some.key
                - some-key-with-placeholder.*

You first need to define the namespace you want to export for (see above for details). Then you need to define the domain you want to extract the message from.

And then you need to list all message keys that you want to export. You can either list them individually or use the * placeholder. The placeholder can stand anywhere in the text, you can also use multiple placeholders.

It might make sense to group all translations from the frontend to reduce an excessive number of extract list entries.

Initializing the JS-Translator

In the Mayd backend, the translator is already initialized and accessible via the app.get<Translator>("translator") service.

First you need to export the data container in Twig:

{{- javascript_translations_init("app") -}}
parameters
nametypedefaultdescription
namespacestringThe namespace to embed the translations for.
localestring|nullnullThe locale to embed the translations for. By default the request locale.

The initialization is done in a single call, by using a mojave helper:

const translator = initFromGlobalData(
    "TranslatorInit",
    new Translator("messages")
);

The Translator takes the default message domain as constructor argument. It makes sense to set it to messages in the frontend (in Mayd it’s automatically backend).

If the <script> tag loading the file with this line is after your translation init call above, all your translation will be fully loaded at this point. If your translations are loaded later (or asynchronously) then the translations will only be available once they are loaded. The translator has no checks for that, so only call the translator after your translations are loaded.

Usage

Usage of the JS translator is basically like the Symfony translator:

translator.trans("some.key");
translator.trans("some.other.key", {name: "test"});

// or with custom domain
translator.trans("some.other.key", {name: "test"}, "form");

The translator supports all Intl-ICU features, so things like plurals, dates and selects are all supported.

Translations in Bundles

Symfony bundles can expose translations as well, by exporting them in a compiler pass. Just register the compiler pass like in the following code example, the structure is the same as in the project configuration.

use Becklyn\Translations\DependencyInjection\ExtractTranslationsPass;
use Symfony\Component\HttpKernel\Bundle\Bundle;

class MyBundle extends Bundle
{
    public function build (ContainerBuilder $container) : void
    {
        $container->addCompilerPass(
            new ExtractTranslationsPass([
                "namespace" => [
                    "domain" => [
                        "key.sub.*",
                        "some.other.key",
                    ],
                ],
            ])
        );
    }
}