Translations
Using and based on a2lix and knp translations bundles.
Supported By
- Standard Translatable Search Filters (ex: ?title)
- SearchTermFilter (ex: ?search)
How it works
There are multiple listeners that make up the core of the translatable entities translations.
- AutoFormListener
- BaseControllerListener
- ControllerListener
- TranslatableEventSubscriber
- TranslationsFormsListener
- TranslationsListener
- OneLocaleApiListener
Also, a doctrine filter to only enable 1 locale at the time:
- OneLocaleFilter
And finally another doctrine filter that does not seem to be enabled all the time:
- ManyLocalesFilter
AutoFormListener
PreSetData event for translations in form.
BaseControllerListener
Construct ControllerListener (autowire services).
ControllerListener
Get locale from request and set oneLocale filter locale parameter with it. Exclude any API urls, they are handled in the OneLocaleApiListener.
TranslatableEventSubscriber
Listener that handles Translations load, creation and update on translatable entities. Events:
- Events::postPersist
- Events::postLoad
- Events::prePersist
- Events::postUpdate
Locales are set on prePersist event and on postLoad events.
Function setLocales: set current and default locale on entity, uses locale provider (SimpleProvider).
TranslationsFormsListener
- Handle translations locales required option.
- Handle empty translations on submit and set locale on translations.
TranslationsListener
- Form events
- Does the same thing as TranslationsFormsListener on onSubmit event?? To review…
OneLocaleApiListener
Handle oneLocale filter on API request.
On translations endpoint request, the OneLocaleFilter is disabled, to have the capacity to read or write on all translations.
On “normal” entity endpoint, if it is a Translatable entity, then the query param “_locale” can overwrite the default locale.
For example: /open-api/v3/products/4?_locale=en_CA will set the en_CA locale on the request. If the locale is not found, it fallback on the default locale.
It also disables the TranslatableEventSubscriber, to avoid unexpected behavior from the API, because the translations should not be updated or created from a translatable POST/PUT.
OneLocaleFilter
SQLFilter to limit translations queries to only return translations in the current locale. Only active on entities that implements OneLocaleInterface.
ManyLocalesFilter
SQLFilter to limit translations queries to only return translations in the given locales. Only active on entities that implements ManyLocalesInterface.
- As of now, none of the entities implements the ManyLocalesInterface.
Repository setup + Crud controller setup
A addJoinTranslations function has been added to easily add the translations join necessary to fetch the translations for a translatable table. It adds the join on a given QueryBuilder.
The function exists in EntityRepositoryTrait and Crud.
In EntityRepositoryTrait there is also a function named addTranslationsSearchFields which adds
the translation search fields for a translatable entity.
These functions are called in all base query functions, like getBaseListingQueryBuilder, because it is a standard way of adding a standard (for all translatable) property.
API
We can now post translations, thanks to the TranslationStateProcessor!
There are two ways of doing so.
Metadata
First, you need to get the ‘translationTitlePropertyName’ and the ‘translationTitlePropertyDescription’
To find those, go to the metadata endpoint of your entity at /open-api/v3/{entityShortName}/metadata/{id} or /open-api/v3/metadata/entity/{entityFQCN}
Api Translations Object
To send multiple translations on an entity on one go, this is the best way!
Just add this object to your body post:
"apiTranslations": {
"fr_CA": {
"name": "TEST FR",
"description": "<p>TEST FR</p>"
},
"en_CA": {
"name": "TEST EN",
"description": "<p>TEST EN</p>"
}
},The ‘name’ is the value you got from the translationTitlePropertyName… So let’s say translationTitlePropertyName=title, replace ‘name’ with ‘title’
Do the same for description, using the value provided by the ‘translationTitlePropertyDescription’ field
_locale as Query Param
You can also send translations for a specific locale using the query param _locale:
/open-api/v3/{entity}?_locale=fr_CA
And in your pst body, directly send the ‘translationTitlePropertyName’ and ‘translationTitlePropertyDescription’ as so:
{
[...]
"name": "TEST FR",
"description": "<p>TEST FR</p>"
[...]
}Searching from all translations (searchThroughAllLocales Query Param)
You can use the queryparam searchThroughAllLocales to disable the doctrine filter on locale, in combination with your translatable search filters.
This allows fo the filter to apply search terms on ALL translations for a specific translatable.
Supported by: SearchTermFilter, TranslationSearchFilter
Ex:
/open-api/v3/notes?search=FR&properties[title]=true&searchThroughAllLocales=true&_locale=en_CA
/open-api/v3/notes?title=FR&properties[title]=true&searchThroughAllLocales=true&_locale=en_CA
/open-api/v3/notes?title_end_with=FR&properties[title]=true&searchThroughAllLocales=true&_locale=en_CA
Related
- Lang Translations API & Usage (frontend) — how the CRUD consumes this
- Entity Interfaces & Behaviors —
TranslatableInterface