Мультиязычность 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
2020-04-06 18:43

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

Ответить
Arunas
2020-04-07 07:21

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

Ответить
Дмитрий Елисеев
2020-04-07 16:44

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

Ответить
Arunas
2020-04-08 06:27

спасибо

Ответить
Руслан
2020-04-11 09:13

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

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

Спасибо.

Ответить
Дмитрий Елисеев
2020-04-18 15:04

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

Ответить
Руслан
2020-04-18 15:25

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

Ответить
KonTuzh
2020-04-12 00:42

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

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

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

Ответить
Дмитрий Елисеев
2020-04-18 15:15

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

Для фронтенда можно установить 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
2021-03-22 16:50

Не проходит 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())) {

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

Ответить
Дмитрий Елисеев
2021-03-22 17:44

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

Ответить
Руслан
2021-08-08 11:51

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

Ответить
Дмитрий Елисеев
2021-08-16 17:54

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

Ответить
Dzianis
2022-09-24 18:15

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

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

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

Ответить
Михаил
2023-02-07 04:32

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

Ответить
Дмитрий Елисеев
2023-02-07 13:37

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

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

Ответить
Руслан
2023-07-28 10:02

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

Ответить
Руслан
2023-08-01 22:00

пока решил через костыль, передавая в строке проксируемого запроса /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;
}

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

Ответить
Дмитрий Елисеев
2023-08-24 14:32

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

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

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

Yandex
MailRu
GitHub
Google