Skip to content

Symfony UX Translator

Edit this page

EXPERIMENTAL This component is currently experimental and is likely to change, or even change drastically.

Symfony UX Translator is a Symfony bundle providing the same mechanism as Symfony Translator in JavaScript with a TypeScript integration, in Symfony applications. It is part of the Symfony UX initiative.

The ICU Message Format is also supported.

Installation

Note

This package works best with WebpackEncore. To use it with AssetMapper, see Using with AssetMapper.

Caution

Before you start, make sure you have StimulusBundle configured in your app.

Install the bundle using Composer and Symfony Flex:

1
$ composer require symfony/ux-translator

If you're using WebpackEncore, install your assets and restart Encore (not needed if you're using AssetMapper):

1
2
$ npm install --force
$ npm run watch

After installing the bundle, the following file should be created, thanks to the Symfony Flex recipe:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// assets/translator.js

/*
 * This file is part of the Symfony UX Translator package.
 *
 * If folder "../var/translations" does not exist, or some translations are missing,
 * you must warmup your Symfony cache to refresh JavaScript translations.
 *
 * If you use TypeScript, you can rename this file to "translator.ts" to take advantage of types checking.
 */

import { trans, getLocale, setLocale, setLocaleFallbacks } from '@symfony/ux-translator';
import { localeFallbacks } from '../var/translations/configuration';

setLocaleFallbacks(localeFallbacks);

export { trans }
export * from '../var/translations';

Usage

When warming up the Symfony cache, your translations will be dumped as JavaScript into the var/translations/ directory. For a better developer experience, TypeScript types definitions are also generated aside those JavaScript files.

Then, you will be able to import those JavaScript translations in your assets. Don't worry about your final bundle size, only the translations you use will be included in your final bundle, thanks to the tree shaking.

Configuring the dumped translations

By default, all your translations will be exported. You can restrict the dumped messages by either including or excluding translation domains in your config/packages/ux_translator.yaml file:

1
2
3
4
5
6
7
8
ux_translator:
        domains: ~    # Include all the domains

        domains: foo  # Include only domain 'foo'
        domains: '!foo' # Include all domains, except 'foo'

        domains: [foo, bar]   # Include only domains 'foo' and 'bar'
        domains: ['!foo', '!bar'] # Include all domains, except 'foo' and 'bar'

Configuring the default locale

By default, the default locale is en (English) that you can configure through many ways (in order of priority):

  1. With setLocale('de') or setLocale('de_AT') from @symfony/ux-translator package
  2. Or with <html data-symfony-ux-translator-locale="{{ app.request.locale }}"> attribute (e.g., de_AT or de using Symfony locale format)
  3. Or with <html lang="{{ app.request.locale|replace({ '_': '-' }) }}"> attribute (e.g., de-AT or de following the W3C specification on language codes)

Detecting missing translations

By default, the translator will return the translation key if the translation is missing.

You can change this behavior by calling throwWhenNotFound(true):

1
2
3
4
5
6
7
8
9
10
11
// assets/translator.js

- import { trans, getLocale, setLocale, setLocaleFallbacks } from '@symfony/ux-translator';
+ import { trans, getLocale, setLocale, setLocaleFallbacks, throwWhenNotFound } from '@symfony/ux-translator';
  import { localeFallbacks } from '../var/translations/configuration';

  setLocaleFallbacks(localeFallbacks);
+ throwWhenNotFound(true)

  export { trans }
  export * from '../var/translations';

Importing and using translations

If you use the Symfony Flex recipe, you can import the trans() function and your translations in your assets from the file assets/translator.js.

Translations are available as named exports, by using the translation's id transformed in uppercase snake-case (e.g.: my.translation becomes MY_TRANSLATION), so you can import them like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// assets/my_file.js

import {
    trans,
    TRANSLATION_SIMPLE,
    TRANSLATION_WITH_PARAMETERS,
    TRANSLATION_MULTI_DOMAINS,
    TRANSLATION_MULTI_LOCALES,
} from './translator';

// No parameters, uses the default domain ("messages") and the default locale
trans(TRANSLATION_SIMPLE);

// Two parameters "count" and "foo", uses the default domain ("messages") and the default locale
trans(TRANSLATION_WITH_PARAMETERS, { count: 123, foo: 'bar' });

// No parameters, uses the default domain ("messages") and the default locale
trans(TRANSLATION_MULTI_DOMAINS);
// Same as above, but uses the "domain2" domain
trans(TRANSLATION_MULTI_DOMAINS, {}, 'domain2');
// Same as above, but uses the "domain3" domain
trans(TRANSLATION_MULTI_DOMAINS, {}, 'domain3');

// No parameters, uses the default domain ("messages") and the default locale
trans(TRANSLATION_MULTI_LOCALES);
// Same as above, but uses the "fr" locale
trans(TRANSLATION_MULTI_LOCALES, {}, 'messages', 'fr');
// Same as above, but uses the "it" locale
trans(TRANSLATION_MULTI_LOCALES, {}, 'messages', 'it');

Using with AssetMapper

Using this library with AssetMapper is possible, but is currently experimental and may not be ready yet for production.

When installing with AssetMapper, Flex will add a few new items to your importmap.php file. 2 of the new items are:

1
2
3
4
5
6
'@app/translations' => [
    'path' => 'var/translations/index.js',
],
'@app/translations/configuration' => [
    'path' => 'var/translations/configuration.js',
],

These are then imported in your assets/translator.js file. This setup is very similar to working with WebpackEncore. However, the var/translations/index.js file contains every translation in your app, which is not ideal for production and may even leak translations only meant for admin areas. Encore solves this via tree-shaking, but the AssetMapper component does not. There is not, yet, a way to solve this properly with the AssetMapper component.

Backward Compatibility promise

This bundle aims at following the same Backward Compatibility promise as the Symfony framework: https://symfony.com/doc/current/contributing/code/bc.html

This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.
TOC
    Version