1

I run a multi-language Symfony 4.4 website where the locale is part of the URL. So I have /it/, /fr/ and so on.

My routes look like this:

    /**
     * @Route({
     *     "it": "/it/azienda/",
     *     "es": "/es/empresa/"
     * }, name="app_cms_about")
     */

Then I've a pre-controller event that set the correct locale:

public function onRouteRequest(ControllerEvent $event) 
{
    //  ... checks and stuff ...

    $event->getRequest()->setLocale($ln);
}

Everything works as expected via web, but now I need to manage this language difference in a CLI Command: basically it means that when I run $this->urlGenerator->generate('app_cms_about') from the CLI, I expect to get the locale-based URL.

The user must pass the locale to the CLI Command to as an argument:

protected function configure()
{
   $this->addArgument(
          "app_language",
          InputArgument::REQUIRED,
          'The site to run on: `it`, `es`, ...');
}

Now I just need to set this somehow. I'd love to it with an event, but of course there is no getRequest() on the CLI event to set the locale on.

How do I set the locale on a Symfony 4 CLI Command?

yivi
  • 42,438
  • 18
  • 116
  • 138

2 Answers2

1

Setting the locale does not make a lot of sense for a console application. What has a locale is the user request, and there is no request during a command line run.

But you want seems to be to be able to get URLs with the appropriate locale:

Then, straight from the docs:

When a route is localized, Symfony uses by default the current request locale. Pass a different '_locale' value if you want to set the locale explicitly

E.g.:

$aboutUrlIt = $this->router->generate('app_cms_about', ['_locale' => 'it']);

You mention in comments the setting default_locale, and that since you can change this it means console applications "have a locale set". But you are reaching the wrong conclussion from this: this setting is to set a default locale in case where no locale is set in the request. Or, for example, when there is no request, as in a command line application.

You cannot change that setting during runtime, because that setting is part of the compiled container, which is compiled before the application is run.

yivi
  • 42,438
  • 18
  • 116
  • 138
  • thanks @yivi , that makes sense. But I'm looking for a way to change the locale for the whole application. Yes, the locale is set, even for a console application: I can tell because, if I change the parameter `framework: default_locale` in `config/packages/translation.yaml`, the whole console application works differently. – Dr. Gianluigi Zane Zanettini Mar 14 '22 at 19:18
  • No, the locale is not set. What you are changing is the "default locale", e.g. what "locale to use if no locale is set". For example, while executing a console command. You cannot change the 'default locale' at runtime, because that's part of the compiled container. – yivi Mar 14 '22 at 19:19
  • 1
    Makes sense, thanks for your explanation, I appreciate it. – Dr. Gianluigi Zane Zanettini Mar 14 '22 at 19:23
0

Following Symfony calls with xdebug I was able to find the solution I was looking for. I built a listener as the one I'm using via web:

services:
    App\EventListener\CommandStartListener:
        tags:
            - { name: kernel.event_listener, method: onCommandStart,  event: console.command }
<?php
namespace App\EventListener;

use Symfony\Component\Console\Event\ConsoleCommandEvent;
use Symfony\Component\Routing\RouterInterface;


class CommandStartListener
{
    protected RouterInterface $router;


    public function __construct(RouterInterface $router)
    {
        $this->router   = $router;
    }


    public function onCommandStart(ConsoleCommandEvent $event) : ?string
    {
       //  ... checks and stuff ...

        try {

            $lnParam = $event->getInput()->getArgument("app_language");

        } catch( \Exception $ex) {

            return null;
        }


        $this->router->getContext()->setParameter('_locale', $lnParam);
        return $lnParam;
    }
}

This makes any urlGenerator->generate() behave correctly.

hat tip to @yivi for pointing me into the right direction.

7ochem
  • 2,183
  • 1
  • 34
  • 42
  • But this is **not** what the question was asking, though. This is an event listener that will affect the router for all commands, which might not be necessarily what one wants, nor the answer to the question as posed. – yivi Mar 14 '22 at 20:18
  • I'm sorry if I was unable to make the question more clear. This is exactly what I was looking for anyway. Thanks again for your support. – Dr. Gianluigi Zane Zanettini Mar 14 '22 at 20:23