54K Views

Translation in symfony

Providing content in multiple languages is a necessity for a good web design. But implementing it can be hectic. Although There are tools like Google Translator,  Bing Translator. But most of the time, they are not relevant to our needs due to their limited customizability.

So, we will opt for a better way by using Translation from Symfony.here, I am going to describe how anyone can easily set up internationalization in Symfony. In this article, I will use YML(YAML) format for translation files. In this article, single characters like ‘, ~ are enclosed in bracket (~) for readability.

Translation Component is part of Symfony framework. You can also read official doc .

Setup Translation:

Before using translation in Symfony you will need to enable translator service.

# app/config/config.yml
framework:
    translator: { fallbacks: [en] }
    default_locale: en

Translator Service uses special _locale parameter for getting Current locale(language). When using the special _locale parameter in a route, the matched locale is automatically set on Request and can be retrieved via the getLocale() method.

In other words, if a user visits the URI, /en/somepage the locale en will automatically be set as the locale for the current request. If no locale is present then fallback locale from app/config/config.yml is used.

so, Sample Multilingual URL will look like

# app/config/routing.yml
about_us:
    path:     /{_locale}/about
    defaults: { _controller: AppBundle:About:index }
    requirements:
        _locale: en|fr|de

Now, we have a multilingual Url /{_locale}/about which could be used as /en/about , /fr/about etc.

Now, we need to translate every readable Sentence in controller and Template file(s) for viewing.

Translating content in Controller:

In symfony controller, you can use translation as:

$message = $this->get('translator')->trans('Hello there');

Symfony also supports translation for dynamic string (with variables) like:

‘I have a ‘.$something

 

$this->get('translator')->trans('I have a %something%', [
                    %something% => $something,
]);

So, we don’t need to write different translation for ‘I have a pen’ and ‘I have a apple’. we could use dynamic string ‘I have a %something%’ for both in above given manner. variable in such strings is called Message Placeholder.

Note: In Symfony service(s), we can pass translator service using

  1. using translator argument
    # config/services.yml
        my.service:
            class: Webkul\AppBundle\Services\MyService
            arguments: [@translator]

    Then using translator as:

    $this->translator->trans('Hello world');
  2. using container
    # config/services.yml
        my.service:
            class: Webkul\AppBundle\Services\MyService
            arguments: [@service_container]

    Then using translator as:

    $this->container->get('translator.default')->trans('Hello world');

Translating content in Template:

Symfony provides support for PHP as well as Templates. so, we could translate content in Twig Template(s) like:

Method 1:

{% trans %}Hello World{% endtrans %}

Method 2:

{{ 'Hello World'|trans }}

Note: Method 2 (|trans) is safer to use than method 1 ({% trans %})  because |trans escapes even unsafe strings.

Example: While using {% trans %}Password{% endtrans %}, Password may be translated to Parola d’ordine in Italian, due to which (‘) may break string in javascript. You can avoid escaping issues using (|trans ) like {{ ‘Password’|trans }}

Translating Dynamic string (containing variables) in twig:

We can translate dynamic strings like ‘This is a %something%’ as:

{{ 'This is a %something%'|trans({ '%something%': somethingVar }) }}

For more sophisticated dynamic string, we can do something like:

{{ 'I have %count% cool %things%'|trans({ 
         '%count%': count, '%things%': thingName 
}) }}

We can even translate variable in dynamic string like:

{{ 'I have a cool %things%'|trans({
         '%thing%': 'Thing'|trans ~ thingName
}) }}

Sometimes we may need to translate content containing HTML. then we can use |raw filter with |trans.

Like For Html, Click this <a href=”#”>link</a> for more info.

{{ 'Click this %link% for more info.'|trans({
         '%link%': '<a href="#">' ~ 'link'|trans ~ '</a>'
})|raw }}

Note: (~) is concatenation operator in twig.

Create loader files for translations:

Symfony doesn’t automatically convert translated message(s) to _locale language, You have to manually save translation for all messages in translation files.

According to doc, Symfony looks for message files (i.e. translations) in the following default locations:

  • the app/Resources/translations directory;
  • the app/Resources/<bundle name>/translations directory;
  • the Resources/translations/ directory inside of any bundle.

Naming Translation Files

The filename of the translation files is also important:

A message file in any of above given locations should be in format: 

domain.locale.loader

  • domain: default: messages (any name, used for grouping messages)
  • locale: The locale that the translations are for (e.g. en_GB, en, etc);
  • loader: How Symfony should load and parse the file (e.g. yml, php, xlf etc).

Example: Name for english (en) _locale file with yml will be messages.en.yml.

_locale Format File Name
fr yml messages.fr.yml
ru yml messages.ru.yml
de xlf messages.de.xlf

Storing Messages in translation files:

Data in translated yml files can be stored as :

# messages.fr.yml
Hello world: Bonjour le monde

key, values in yml files should be seperated by (:) followed by space i.e. (: )

Note: translation string are Case-sensitive, so you need add separate translation for ‘Hello World’ and ‘hello world’ .

Yml files contains key, value separated by (:), so yml file may become malformed if there is string like

Putin asked Trump: Why?: Putin a demandé Trump: pourquoi?

We should correctly format yml file, to avoid malformed yml file error.

How to correctly format yml files?

1. Enclose key, values in delimiter (‘) or (“)

Example:

"Putin asked Trump: Why?": "Putin a demandé Trump: pourquoi?"

2.You may need to escape (‘) or (“) when using these as delimiter

Example:

"Who doesn't?": "Who doesn't?"
'Who doesn''t?': 'Who doesn''t?'

Note: single inverted comma can be escaped by adding a extra single inverted comma
i.e. (‘) can be escaped by using (”)

3. For complex and multiline sentences use >- operator like:

Complex text with charcters ' : & "?: >-
    Complex text with charcters ' : & "?
 Once new translations are added, we need to clear cache for using them:

for symfony 3.x

php bin/console cache:clear

for symfony 2.x

php app/console cache:clear

We could use command given below to find missing translation string(s) in a Bundle:

 php app/console debug:translation fr AcmeDemoBundle --only-missing

What’s more?

You can visit these links for more information about translation in symfony:

http://symfony.com/doc/current/translation.html

http://symfony2-document.readthedocs.io/en/latest/book/translation.html

http://yaml.org/spec/current.html#id2534365

. . .

Comment

Add Your Comment

Be the first to comment.

css.php