Мультиязычность API

Добавление мультиязычности к API. Перевод сообщений валидации и доменных ошибок. Автораспознавание заголовка Accept-Language.

  • 00:00:39 Подходы к мультиязычности
  • 00:02:53 Тест на перевод ошибок валидации
  • 00:03:59 Переводы для валидатора
  • 00:04:58 Компонент Translation
  • 00:06:44 Подключение переводчика к валидатору
  • 00:11:34 Автоматическое переключение языков
  • 00:12:14 Посредник TranslatorLocale
  • 00:16:53 Парсинг Accept-Language
  • 00:20:23 Тест TranslatorLocaleTest
  • 00:23:13 Перевод доменных исключений
  • 00:27:43 Повторное использование посредников
  • 00:29:32 Публикация посредников на примере DomainExeptionHandler
Скрытый контент (код, слайды, ...) для подписчиков. Открыть →
Дмитрий Елисеев
elisdn.ru
Комментарии (19)
Arunas

Да, очень солидно и интересно, спасибо.

Ответить
Arunas

здесь, как понимаю, настройка языка и перевод происходит автоматически (от locale), а что если пользователь из России захочет английский текст - напр. ошибки в английском тексте?

Ответить
Дмитрий Елисеев

Язык выбирается автоматически по HTTP-заголовку Accept-Language при запросе API. Так что может либо отправить запрос без заголовка, либо со значением en

Ответить
Arunas

спасибо

Ответить
Руслан

Дмитрий, спасибо за как всегда очень содержательный и интересный урок!

Хотел узнать, будет ли затронута тема использования GraphQL для ReactJS клиента на базе текущего Slim API? Если в данном проекте это оверхед, то может Ваши критерии когда это актуально, преимущества/недостатки (н-р. легче поддерживать версионирование API, снижение количества запросов к API и др.), рекомендации использовать с Apollo-server или без и пр.

Спасибо.

Ответить
Дмитрий Елисеев

Да, поговорим про него.

Ответить
Руслан

Супер, спасибо!

Ответить
KonTuzh

Дмитрий, спасибо за такое подробное объяснение!

При последней проверке кода psalm на файле ValidationExceptionHandler начал ругаться на отсутствие интерфейса Stringable, который указан в Symfony\Component\Validator\ConstraintViolationInterface в качестве возвращаемого типа данных для метода getMessage. Насколько я понял, этот класс появится/появился в PHP8, а у нас 7.4. Так что пришлось дополнительно поставить пакет symfony/polyfill-php80

Возможно, я забегаю вперед и этот момент еще будет разбираться в будущем... у меня вопрос по локализации самого сайта: меню, статьи и другой контент страниц. Каким образом лучше это организовать в базе данных? Разные таблицы? Разделение на разные записи в одной таблице с различием по полю locale?

Ответить
Дмитрий Елисеев

Локализовать сайт не будем.

Для фронтенда можно установить react-localize-redux, добавить переводы и вызывать:

<Translate id="menu.about">About</Translate>

А для бэкенда можно переводимый контент вынести в отдельную коллекцию:

class Post {
    private Id $id;
    private string $slug;
    private Collection<Content> $contents;
    private Status $status;
}

class Content
{
    private string $lang;
    private string $title;
    private string $text;
}
Ответить
Ruslan

Не проходит psalm (commit Added domain exception translation от 17.03.2020):

ArgumentTypeCoercion - config/common/doctrine.php:45:38 - Argument 2 of Doctrine\DBAL\Types\Type::addType expects class-string<Doctrine\DBAL\Types\Type>, parent type string provided
                Type::addType($name, $class);

MixedArgumentTypeCoercion - config/common/doctrine.php:58:13 - Argument 1 of Doctrine\ORM\EntityManager::create expects Doctrine\DBAL\Connection|array<string, mixed>, parent type array<array-key, mixed> provided
            $settings['connection'],

InvalidArrayOffset - config/common/mailer.php:44:23 - Cannot create offset of type false|string, expecting array-key
            'from' => [getenv('MAILER_FROM_EMAIL') => 'Auction'],

MixedArgumentTypeCoercion - src/Auth/Entity/User/User.php:253:33 - Type mixed should be a subtype of App\Auth\Entity\User\UserNetwork
        return $this->networks->map(static function (UserNetwork $network) {

MixedAssignment - src/Auth/Entity/User/UserRepository.php:78:14 - Unable to determine the type that $user is being assigned to
        if (!$user = $this->repo->find($id->getValue())) {

Как правильно с ними поступить?

Ответить
Дмитрий Елисеев

Исправить, как мы сделали это в следующих эпизодах.

Ответить
Руслан

Дима, может сталкивались, как можно отключить со стороны приложения автоматическое срабатывание в браузере Google translate (Chrome etc.)? Спасибо большое!

Ответить
Дмитрий Елисеев

Всегда отключаю вручную через "Никогда не переводить этот сайт". Автоматически не знаю как.

Ответить
Dzianis

Дмитрий, огромное спасибо за эти серии.

Просмотрел уже 30% из доступных уроков и хочу сказать что вы просто СУПЕР-преподаватель! Объяснения, детали, подача, то как структурирован материал - огромная работа!

Я очень рад что google привел меня на ваш сайт :)

Ответить
Михаил

Почему у всех middleware приватные методы статичные? Это оптимизация какая-то?

Ответить
Дмитрий Елисеев

Это функции, которые не используют текущий объект из $this. Поэтому и нет повода их делать динамическими методами, которые привязаны к каждому объекту.

Их проще объявить отдельной PHP-функцией снаружи класса или статическим методом внутри класса.

Ответить
Руслан

Дмитрий, здравствуйте, в провайдере аутентификации на React вы делаете редирект на форму аутентификации бэкенда через window.location.assign, где нельзя передавать headers, как быть с локализацией?

Ответить
Руслан

пока решил через костыль, передавая в строке проксируемого запроса /api/{ru|en}/authorize на фронтенде, и там же в nginx подчищая его через rewrite, передавая нужный Accept-Language

location ~* ^/api/(?<lang>en|ru)/(?<path>.*)$ {
   set $upstream http://api;
   rewrite ^ /$path break;
   proxy_set_header  Host $host;
   proxy_set_header  Accept-Language $lang;
   proxy_pass        $upstream;
   proxy_redirect    off;
}

Интересует как будет Вами реализовано в проекте

Ответить
Дмитрий Елисеев

Да, либо указывать язык в пути /ru/authorize, либо передавать отдельным параметром вроде &lang=ru, либо оставить как есть, чтобы бэкенд ориентировался по умолчанию на язык браузера.

Ответить
Зарегистрируйтесь или войдите чтобы оставить комментарий

Или войти через:

Yandex
MailRu
GitHub
Google