There is a bundle for routing internationalization called BeSimpleI18nRoutingBundle but it is not available for symfony 4 right now.
Core symfony implementation
With core symfony you could use multiple routes for each controller, that would have a {_locale} parameter with default value, here the problem would be that two different URLs would be returning the same page.
e.g /test would be the same as /test/en
This might cause problems with SEO
here how the annotations would look like if you wish to implement this method
/**
* @Route("/test/{_locale}", defaults={"_locale"="en"}, requirements={"_locale":"en"}, name="default_en")
* @Route("/δοκιμή/{_locale}", defaults={"_locale"="el"}, requirements={"_locale":"el"}, name="default_el", options = {"utf8": true})
* @Route("/tester/{_locale}", defaults={"_locale"="fr"}, requirements={"_locale":"fr"}, name="default_fr")
*/
public function test($_locale)
{
return new Response("Your current locale is : $_locale");
}
Dynamic Route
Another option is to create a Routing Service that would apply your logic.
Here is an example.
this would be the controller that handles all the paths
Controller
namespace App\Controller;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use App\Service\Router;
class RouterController extends Controller {
/**
* @Route("/{path}", name="router", requirements={"path" = ".+"})
*/
public function router($path,Request $request,Router $router) {
$result=$router->handle($path);
if($result){
$result['args']['request']=$request;
return $this->forward($result['class'], $result['args']);
}
throw $this->createNotFoundException('error page not found!');
}
}
This Controller Action depends on a service called Router so you will have to create a Router service that would return the an array (you can change it to return a custom object) with keys class and args that would be used to forward the request to a controller action.
Service
/src/Service/Router.php
Here you should implement a function called handle and you can apply any logic to it
here is a basic example
namespace App\Service;
class Router
{
public function handle($path)
{
switch ($path) {
case "test":
return [
"class" => "App\Controller\TestController::index",
"args" => [
"locale" => 'en'
]
];
case "tester":
return [
"class" => "App\Controller\TestController::index",
"args" => [
"locale" => 'fr'
]
];
default:
return false;
}
}
}
The code above would forward the request to TestController::index function and will add as parameter to that function the locale variable and also it will include the Request object
You could store the routes in a yaml file or database or any other location you like. You can manipulate the $path variable to extract information about id, page etc.