how to use default locale in symfony3.4 routes - symfony

I want to open my websites like these:
http://127.0.0.1:8000/ (Works)
http://127.0.0.1:8000/en/ (Works)
http://127.0.0.1:8000/en/mrg (Works)
http://127.0.0.1:8000/mrg (Doesn't Work)
So I put this code in routing.yml:
teach:
resource: "#TeachBundle/Controller/"
type: annotation
prefix: /{_locale}
requirements:
_locale: "|en|fa"
and my controller is like this:
/**
* #Route("/mrg")
*/
public function mrgAction(Request $request)
{
$lang=$request->getLocale();
return new Response("<html><body>Your language: <b> $lang </b></body></html>");
}
All urls worked but http://127.0.0.1:8000/mrg doesn't work and returns:
No route found for "GET /mrg"
I need use default language for example if I try to open http://127.0.0.1:8000/mrg then open http://127.0.0.1:8000/en/mrg.
Is there any solution to fix this problem?

Add defaults option to your routing configuration to set the default locale if it's not set in your controllers #Routes:
teach:
resource: "#TeachBundle/Controller/"
type: annotation
prefix: /{_locale}
requirements:
_locale: "|en|fa"
defaults:
_locale: 'en' # or '%locale%'

Try this:
{_locale}
/**
* #Route("/{_locale}/mrg")
*/
public function mrgAction(Request $request)
{
$lang=$request->getLocale();
return new Response("<html><body>Your language: <b> $lang </b></body></html>");
}
Setting a Default Locale
# app/config/config.yml
framework:
default_locale: en
If doesn't work, Can You show your app/config/routing.yml.

I advice you to use : BeSimpleI18nRoutingBundle
https://github.com/BeSimple/BeSimpleI18nRoutingBundle
use BeSimple\I18nRoutingBundle\Routing\Annotation\I18nRoute;
class NoPrefixController
{
/**
* #I18nRoute({ "en": "/welcome", "fr": "/bienvenue", "de": "/willkommen" }, name="homepage")
*/
public function indexAction() { }
}

Related

Symfony routing name through yaml

Is it possible in Symfony 4 to set the routing name trough yaml.
So old annotation
/**
* #Route("/cms", name="security_login")
*/
public function loginAction(Request $request, AuthenticationUtils $authenticationUtils) {
// code here
}
Yaml annotation
login:
path: /cms
controller: App\Controller\SecurityController::loginAction
name: security_login
It looks like yaml doesn't support the name key. only the following keys are supported:
"resource", "type", "prefix", "path", "host", "schemes", "methods", "defaults", "requirements", "options", "condition", "controller".
or is the key 'login' the name?
Yes, the "login" key in your file is the route's name.
Click on the "YAML" tabs in the documentation to see yaml examples :
# config/routes.yaml
blog_list:
path: /blog
controller: App\Controller\BlogController::list
blog_show:
path: /blog/{slug}
controller: App\Controller\BlogController::show
Corresponds to these annotations :
/**
* Matches /blog exactly
* #Route("/blog", name="blog_list")
*/
public function list()
{
// ...
}
/**
* Matches /blog/*
* #Route("/blog/{slug}", name="blog_show")
*/
public function show($slug)
{
// ...
}
The name is specified in the yaml entry ...
security_login:
path: /cms
controller: App\Controller\SecurityController::loginAction

Two Routes for one Controller OR Two Routes for a group of actions

Here is the scheme of the required URLs:
/service/getBalance should map to CustomerController::getBalance
/service/addBalance should map to CustomerController::addBalance
/customer/getBalance should map to CustomerController::getBalance
/customer/addBalance should map to CustomerController::addBalance
Here is a simple controller
<?php
namespace AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
class CustomerController extends Controller {
/**
* #Route("/getBalance")
*/
public function getBalanceAction(Request $request) {
}
/**
* #Route("/addBalance")
*/
public function addBalanceAction(Request $request) {
}
} // class CustomerController
Have tried the following ways. None of them worked.
# rounting.yml
v1:
resource: "#AppBundle/Controller/CustomerController.php"
prefix: /service
type: annotation
v2:
resource: "#AppBundle/Controller/CustomerController.php"
prefix: /customer
type: annotation
loading the same resource with different prefix always overrides the previous occurrence (the last one works). The following also doesn't work for the same reason and have the same behavior.
# rounting.yml
v1:
resource: "#AppBundle/Resources/config/routing_customer.yml"
prefix: /service
v2:
resource: "#AppBundle/Resources/config/routing_customer.yml"
prefix: /customer
# routing_customer.yml
getBalance:
path: /getBalance
defaults : { _controller: "AppBundle:Customer:getBalance" }
addBalance:
path: /addBalance
defaults : { _controller: "AppBundle:Customer:addBalance" }
Third not working option:
# rounting.yml
v1:
resource: "#AppBundle/Resources/config/routing_v1.yml"
prefix: / # evenr putting /service here instead of inside
v2:
resource: "#AppBundle/Resources/config/routing_v2.yml"
prefix: / # evenr putting /customer here instead of inside
# routing_v1.yml
getBalance:
path: /service/getBalance
defaults : { _controller: "AppBundle:Customer:getBalance" }
addBalance:
path: /service/addBalance
defaults : { _controller: "AppBundle:Customer:addBalance" }
# routing_v2.yml
getBalance:
path: /customer/getBalance
defaults : { _controller: "AppBundle:Customer:getBalance" }
addBalance:
path: /customer/addBalance
defaults : { _controller: "AppBundle:Customer:addBalance" }
I actually need to route / and /customer to the same controller:
/getBalance and /customer/getBalance.
I want to give two prefixes for a group of methods. How to do that in Symfony?
Conclusion from my trials, #goto's answer and #Cerad's comments:
The last Example above could have worked if I used different route names. Route names are unique though out the whole project (Not just unique in file). v1_getBalance and v2_getBalance.
The other solution is to use a custom loader as #goto described.
You could do routes this way:
#Route(
"/{subject}/getBalance",
requirements={
"subject": "customer|service"
}
)
in yml:
subject_getbalance:
path: /{subject}/getBalance
requirements:
subject: customer|service
The requirement is safer than nothing: it allows you to route another route like foo/getBalance on another controller (as it does not match the requirement)
EDIT: for your special case, as you need /getBalance to map to your route too you could do:
subject_getbalance:
path: /{subject}/getBalance
default: { _controller: YourBundle:Controller }
requirements:
subject: customer|service
default_getbalance:
path: /getBalance
default: { _controller: YourBundle:Controller, subject: customer }
Edit: the last idea is to a custom route loader (but I've never tried):
class ExtraLoader extends Loader
{
public function load($resource, $type = null)
{
/* ... */
$prefixes = [ 'default_' =>'','customer_' =>'/customer','service_' =>'/service']
// prepare a new route
$path = '/getbalance/{parameter}';
$defaults = array(
'_controller' => 'YourBundle:Actiona',
);
$requirements = array(
'parameter' => '\d+',
);
foreach($prefixes as $prefixName => $prefixRoute) {
$route = new Route($prefixRoute . $path, $defaults, $requirements);
$routes->add($prefixName . 'getBalance', $route);
}
This will allows you to have 3 routes generated:
default_getBalance: /getBalance
customer_getBalance: /customer/getBalance
service_getBalance: /service/getBalance

prefix sylius product show url with locale

I am using sylius v0.18. I want to prefix locale with product show urls.
sylius_core:
routing:
%sylius.model.product.class%:
field: slug
prefix: /p
defaults:
controller: sylius.controller.product:detailsAction
repository: sylius.repository.product
sylius:
template: SyliusWebBundle:Frontend/Product:show.html.twig
criteria: {slug: $slug}
permission: false
I can use a static word as the prefix in this configuration. but It does not work with _locale. prefix: /{_locale}/p
I found a solution, by overiding getRouteCollectionForRequest method in Sylius\Bundle\CoreBundle\Routing\RouteProvider class with the following configuration.
sylius_core:
routing:
%sylius.model.product.class%:
field: slug
prefix: /{_locale}/p
defaults:
controller: sylius.controller.product:detailsAction
repository: sylius.repository.product
sylius:
template: SyliusWebBundle:Frontend/Product:show.html.twig
criteria: {slug: $slug}
permission: false
parameters:
sylius.route_provider.class: App\AppBundle\Routing\Provider\RouteProvider
class RouteProvider extends BaseProvider
{
/**
* {#inheritdoc}
*/
public function getRouteCollectionForRequest(Request $request)
{
//Overide this method to match the url with _locale
}

Get browser locale automatically

I'm trying to internationalize my website using Symfony.
This is my routing.yml:
index:
pattern: /{_locale}
defaults: { _controller: AppBundle:Index:index, _locale: en }
requirements:
_locale: en|fr
When the URL is just "/", "en" locale is set automatically, this is great but I want the browser locale.
For exemple, if I'm in France and I type "/", I want redirect to "/fr/", etc.
Can you help me?
you can get client locale and set redirection in controller
$clientLocale = strtolower(str_split($_SERVER['HTTP_ACCEPT_LANGUAGE'], 2)[0]);
switch ($clientLocale) {
case 'fr':
return $this->redirect($this->generateUrl('fr_route'));
break;
default:
return $this->redirect($this->generateUrl('en_route'));
break;
}
Based on b3da answer, I'll apply it only for the index route (as I think that is the main case when someone type your domain without params) and relying on my YML translations:
#routing.yml
index:
path: /
defaults:
_controller: AppBundle:Pub:index
index2:
path: /{_locale}
defaults:
_controller: AppBundle:Pub:index
#PubController.php
public function indexAction($_locale=null, Request $request) {
if (!$_locale) {
$browserLocale = strtolower(str_split($_SERVER['HTTP_ACCEPT_LANGUAGE'], 2)[0]);
return $this->redirect($this->generateUrl('index2', ['_locale' => $browserLocale]));
}
return $this->render('AppBundle::index.html.twig', []);
}
If the local browser is not translated on your app/Resources/translation YMLs then it will render the texts using your fallback locale (app/config/parameters.yml).

How to declare both method in routing.yml Symfony2?

I want to declare both methods GET and POST for a same route in my routing.yml.
According the documentation it's possible with annotations like that :
/**
* #Route("/edit/{id}")
* #Method({"GET", "POST"})
*/
But how to YAML ? I tried different things :
contact_envoi:
pattern: /contact-envoi
defaults: { _controller: AcmeDemoBundle:Default:contactEnvoi }
requirements:
sf_method: ['get','post']
and
...
requirements:
_method: { 'GET', 'POST' }
but it still doesn't work ... Please help, I found nothing in the documentation about that.
Thanks to Touki for his comment, it works!
I had to declare twice the same URL on two separate shares and each with their own method as explained here for Symfony 2.1 and here for Symfony 2.2.
contact:
path: /contact
defaults: { _controller: AcmeDemoBundle:Main:contact }
methods: [GET]
contact_process:
path: /contact
defaults: { _controller: AcmeDemoBundle:Main:contactProcess }
methods: [POST]
You can get the same route with the GET and POST methods.
contact:
path: /contact
defaults: { _controller: AcmeDemoBundle:Main:contact }
methods: ['GET','POST']
Then manage in your controller the method used.
public function contactAction(Request $request)
{
if ('POST' === $request->getMethod()) {
..
}
}
just remove the methods
contact:
path: /contact
defaults: { _controller: AcmeDemoBundle:Main:contact }

Resources