Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doc(translatable): Improve the LocaleSubscriber implementation #715

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 38 additions & 18 deletions docs/translatable-api-platform.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Translatable - API Platform

How to use Translatable with API platform.
## Expose translated properties

How to use Translatable with API Platform.

Let's say you have a Document Entity like so:

Expand All @@ -13,7 +15,7 @@ use Knp\DoctrineBehaviors\Model\Translatable\TranslatableTrait;

class Document implements TranslatableInterface
{
use TranslatableTrait;
use TranslatableTrait;

#[ORM\Id]
#[ORM\GeneratedValue]
Expand All @@ -22,8 +24,7 @@ use TranslatableTrait;

public function getTitle(): string
{
return $this->translate()
->getTitle();
return $this->translate()->getTitle();
}
}
```
Expand Down Expand Up @@ -59,7 +60,23 @@ class DocumentTranslation implements TranslationInterface
}
```

Now we can implement an Event Subscriber to listen to the accept-language header on each request:
If you need serialisation groups you must add them on the root entity getter like this:

```php
class Document implements TranslatableInterface
{
use TranslatableTrait;

#[Groups(['document:read', 'search:read'])]
public function getTitle(): string
{
return $this->translate()->getTitle();
}
```

## Set the locale

If you cannot enabled [Symfony `set_content_language_from_locale` option](https://symfony.com/doc/current/reference/configuration/framework.html#set-content-language-from-locale) (happens when you have other parts of your applications where the `Accept-Language` is not the locale provider) you can add your own Event Subscriber like this:

```php
<?php
Expand All @@ -75,6 +92,13 @@ use Symfony\Component\HttpKernel\KernelEvents;

class LocaleSubscriber implements EventSubscriberInterface
{
/**
* @param array<string> $availableLocales
*/
public function __construct(private readonly array $availableLocales)
{
}

/**
* @return array<string, array<int[]|string[]>>
*/
Expand All @@ -88,25 +112,23 @@ class LocaleSubscriber implements EventSubscriberInterface
public function onKernelRequest(RequestEvent $event): void
{
$request = $event->getRequest();
$acceptLanguage = $request->headers->get('accept-language');
if (empty($acceptLanguage)) {
return;
}

$arr = HeaderUtils::split($acceptLanguage, ',;');
if (empty($arr[0][0])) {
// Only set your locale from the Accept Language header
if (!str_starts_with($request->getPathInfo(), '/api')) {
return;
}

// Symfony expects underscore instead of dash in locale
$locale = str_replace('-', '_', $arr[0][0]);

$request->setLocale($locale);
$request->setLocale(
$request->getPreferredLanguage($this->availableLocales)
);
$request->attributes->set('_vary_by_language', true);
}
}
```

Now we can make a request to `/api/documents` do not for get to add the `Accept-Language` header value, in this case it's set to 'cz'.
## Demo

Now we can make a request to `/api/documents`, do not forget to add the `Accept-Language` header value, in this case it's set to 'cz'.
When you change the `Accept-Language` header value, notice the title change language.

```json
Expand All @@ -128,5 +150,3 @@ When you change the `Accept-Language` header value, notice the title change lang
]
}
```

That's it!