JsTranslationBundle
===================
A pretty nice way to expose your Symfony2 translation messages to your client
applications.
**Important:** This documentation has been written for version `2.0.0` and above
of this bundle. For version `1.x`, please read:
[https://github.com/willdurand/BazingaJsTranslationBundle/blob/1.2.1/Resources/doc/index.md](https://github.com/willdurand/BazingaJsTranslationBundle/blob/1.2.1/Resources/doc/index.md).
Also, you might be interested in thisĀ [UPGRADE
guide](https://github.com/willdurand/BazingaJsTranslationBundle/blob/master/UPGRADE.md).
Installation
------------
Install the bundle:
composer require "willdurand/js-translation-bundle"
Register the bundle in `app/AppKernel.php`:
``` php
```
Then add the current application's locale into your layout, by adding a `lang`
attribute to the `html` tag:
```html
```
Now, you are done with the basic setup, and you can specify the [translation
files](http://symfony.com/doc/current/book/translation.html#translation-locations-and-naming-conventions)
you want to load.
### Load Translations
Loading translations is a matter of adding a new `script` tag as follows:
``` html
```
This will use the current `locale` and will return the translated messages found
in each `messages.CURRENT_LOCALE.*` files of your project.
#### Domains
You can add translations that are bound to a given
[domain](http://symfony.com/doc/current/components/translation/introduction.html#using-message-domains):
``` html
```
This will use the current `locale` and will return the translated messages found
in each `DOMAIN_NAME.CURRENT_LOCALE.*` file of your project.
#### Locales
You can use the `locales` **query parameter** to get translations in a specific
language, or to load translation messages in several languages at once:
``` html
```
This will return the translated messages found in each `DOMAIN_NAME.MY_LOCALE.*`
files of your project.
``` html
```
This will return the translated messages found in each `DOMAIN_NAME.(fr|en).*`
file of your project.
#### Loading via JSON
Alternatively, you can load your translated messages via JSON (e.g. using
jQuery's `ajax()` or RequireJS's text plugin). Just amend the above mentioned
URLs to also contain the `'_format': 'json'` parameter like so:
``` html
{{ url('bazinga_jstranslation_js', { '_format': 'json' }) }}
```
Then, feed the translator via `Translator.fromJSON(myRetrievedJSONString)`.
### The `dump` Command
This bundle provides a command to dump the translation files:
php app/console bazinga:js-translation:dump [target]
The optional `target` argument allows you to override the target directory to
dump JS translation files in. By default, it generates files in the `web/js/`
directory.
You have to load a `config.js` file, which contains the configuration for the
JS Translator, then you can load all translation files that have been dumped.
Note that dumped files don't contain any configuration, they only add messages
to the JS Translator.
#### Assetic
The command above is useful if you use
[Assetic](http://symfony.com/doc/current/cookbook/assetic/asset_management.html):
```twig
{% javascripts
'bundles/bazingajstranslation/js/translator.min.js'
'js/translations/config.js'
'js/translations/*/*.js' %}
{% endjavascripts %}
```
In the example above, all translation files from your entire project will be
loaded. Of course you can load specific domains: `js/translations/admin/*.js`.
### The JS Translator
The `Translator` object implements the Symfony2
[`TranslatorInterface`](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Translation/TranslatorInterface.php)
and provides the same `trans()` and `transChoice()` methods:
``` javascript
Translator.trans('key', {}, 'DOMAIN_NAME');
// the translated message or undefined
Translator.transChoice('key', 1, {}, 'DOMAIN_NAME');
// the translated message or undefined
```
> **Note:** The JavaScript is AMD ready.
#### Message Placeholders / Parameters
The `trans()` method accepts a second argument that takes an array of parameters:
``` javascript
Translator.trans('key', { "foo" : "bar" }, 'DOMAIN_NAME');
// will replace each "%foo%" in the message by "bar".
```
You can override the placeholder delimiters by setting the `placeHolderSuffix`
and `placeHolderPrefix` attributes.
The `transChoice()` method accepts this array of parameters as third argument:
``` javascript
Translator.transChoice('key', 123, { "foo" : "bar" }, 'DOMAIN_NAME');
// will replace each "%foo%" in the message by "bar".
```
> Read the official documentation about Symfony2 [message
placeholders](http://symfony.com/doc/current/book/translation.html#message-placeholders).
#### Pluralization
Probably the best feature provided by this bundle! It allows you to use
pluralization exactly like you would do using the Symfony Translator
component.
``` yaml
# app/Resources/messages.en.yml
apples: "{0} There is no apples|{1} There is one apple|]1,19] There are %count% apples|[20,Inf] There are many apples"
```
``` javascript
Translator.locale = 'en';
Translator.transChoice('apples', 0, {"count" : 0});
// will return "There is no apples"
Translator.transChoice('apples', 1, {"count" : 1});
// will return "There is one apple"
Translator.transChoice('apples', 2, {"count" : 2});
// will return "There are 2 apples"
Translator.transChoice('apples', 10, {"count" : 10});
// will return "There are 10 apples"
Translator.transChoice('apples', 19, {"count" : 19});
// will return "There are 19 apples"
Translator.transChoice('apples', 20, {"count" : 20});
// will return "There are many apples"
Translator.transChoice('apples', 100, {"count" : 100});
// will return "There are many apples"
```
For more information, read the official documentation about
[pluralization](http://symfony.com/doc/current/book/translation.html#pluralization).
#### Get The Locale
You can get the current locale by accessing the `locale` attribute:
``` javascript
Translator.locale;
// will return the current locale.
```
By default, the `locale` is set to the value defined in the `lang` attribute of
the `html` tag.
Examples
--------
Consider the following translation files:
``` yaml
# app/Resources/translations/Hello.fr.yml
foo: "Bar"
ba:
bar: "Hello world"
placeholder: "Hello %username%!"
```
``` yaml
# app/Resources/translations/messages.fr.yml
placeholder: "Hello %username%, how are you?"
```
You can do:
``` javascript
Translator.trans('foo');
// will return 'Bar'
Translator.trans('foo', {}, 'Hello');
// will return 'Bar'
Translator.trans('ba.bar');
// will return 'Hello world'
Translator.trans('ba.bar', {}, 'Hello');
// will return 'Hello world'
Translator.trans('placeholder', {} , 'messages');
// will return 'Hello %username%, how are you?'
Translator.trans('placeholder', {} , 'Hello');
// will return 'Hello %username%!'
Translator.trans('placeholder', { "username" : "will" }, 'messages');
// will return 'Hello will, how are you?'
Translator.trans('placeholder', { "username" : "will" }, 'Hello');
// will return 'Hello will!'
Translator.trans('placeholder', { "username" : "will" });
// will return 'Hello will!' as the `Hello` messages have been loaded before the `messages` ones
```
More configuration
------------------
#### Locale Fallback
If some of your translations are not complete you can enable a fallback for
untranslated messages:
``` yaml
bazinga_js_translation:
locale_fallback: en # It is recommended to set the same value used for the
# translator fallback.
```
#### Default Domain
You can define the default domain used when translation messages are added
without any given translation domain:
``` yaml
bazinga_js_translation:
default_domain: messages
```
#### Active locales
By default, all locales are dumped.
You can define an array of active locales:
``` yaml
bazinga_js_translation:
active_locales:
- fr
- en
```
#### Active Domains
By default, all domains are dumped.
You can define an array of active domains:
``` yaml
bazinga_js_translation:
active_domains:
- messages
```
Reference Configuration
-----------------------
``` yaml
# app/config/config*.yml
bazinga_js_translation:
locale_fallback: en
default_domain: messages
```
Testing
-------
### PHP
Setup the test suite using [Composer](http://getcomposer.org/):
$ composer install --dev
Run it using PHPUnit:
$ phpunit
### JavaScript
You can run the JavaScript test suite using [PhantomJS](http://phantomjs.org/):
$ phantomjs Resources/js/run-qunit.js file://`pwd`/Resources/js/index.html