I'm trying to get locale switching to work in the login screen of my application. In order to do that I have links on my login page that point to site.com/ (the default locale) and site.com/en (the second locale I support). As soon as I've logged in, the switching works like a charm. However if I'm not yet authenticated the login always goes back to the default locale. My understanding was that if I use the named routes from FOSUserBundle then it's should be able to handle the locales automatically, but I can't get it to work.
My app/config/security.yml
security:
encoders:
FOS\UserBundle\Model\UserInterface: sha512
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
providers:
fos_userbundle:
id: fos_user.user_provider.username
firewalls:
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_provider: form.csrf_provider
login_path: fos_user_security_login
check_path: fos_user_security_check
logout: true
anonymous: true
access_control:
- { path: ^/_wdt, roles: IS_AUTHENTICATED_ANONYMOUSLY } # allow wdt for debugging
- { path: ^/_profiler/, role: IS_AUTHENTICATED_ANONYMOUSLY } # allow profiler for debugging
- { path: ^/bundles/, role: IS_AUTHENTICATED_ANONYMOUSLY } # allow assets to be loaded anonymously
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin, role: ROLE_ADMIN }
- { path: ^/, role: ROLE_USER }
My app/config/routing.yml
# FOS User bundle
fos_user_security:
resource: "@FOSUserBundle/Resources/config/routing/security.xml"
fos_user_profile:
resource: "@FOSUserBundle/Resources/config/routing/profile.xml"
prefix: /profile
#fos_user_register:
# resource: "@FOSUserBundle/Resources/config/routing/registration.xml"
# prefix: /register
fos_user_resetting:
resource: "@FOSUserBundle/Resources/config/routing/resetting.xml"
prefix: /resetting
fos_user_change_password:
resource: "@FOSUserBundle/Resources/config/routing/change_password.xml"
prefix: /profile
Any pointers much appreciated as I've been stuck with this for a couple of days now
The solution ended up being to prefix the locale to the route imports of FOSUserBundle:
# FOS User bundle
fos_user_security:
resource: "@FOSUserBundle/Resources/config/routing/security.xml"
prefix: /{_locale}
fos_user_profile:
resource: "@FOSUserBundle/Resources/config/routing/profile.xml"
prefix: /{_locale}/profile
fos_user_register:
resource: "@FOSUserBundle/Resources/config/routing/registration.xml"
prefix: /{_locale}/register
fos_user_resetting:
resource: "@FOSUserBundle/Resources/config/routing/resetting.xml"
prefix: /{_locale}/resetting
fos_user_change_password:
resource: "@FOSUserBundle/Resources/config/routing/change_password.xml"
prefix: /{_locale}/profile
And also change the firewall to allow locales in the anonymous routes and configure the logout_path:
security:
encoders:
FOS\UserBundle\Model\UserInterface: sha512
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
providers:
fos_userbundle:
id: fos_user.user_provider.username
firewalls:
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_provider: form.csrf_provider
login_path: fos_user_security_login
check_path: fos_user_security_check
logout:
path: fos_user_security_logout
anonymous: true
access_control:
- { path: ^/_wdt, roles: IS_AUTHENTICATED_ANONYMOUSLY } # allow wdt for debugging
- { path: ^/_profiler/, role: IS_AUTHENTICATED_ANONYMOUSLY } # allow profiler for debugging
- { path: ^/bundles/, role: IS_AUTHENTICATED_ANONYMOUSLY } # allow assets to be loaded anonymously
- { path: ^/[a-z]+/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/[a-z]+/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/[a-z]+/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin, role: ROLE_ADMIN }
- { path: ^/, role: ROLE_USER } # this must be the last match, as url patterns are checked in the order they appear
Using the JMSI18nRoutingBundle would probably be better in the long term, but it did not work as a drop in solution when I tried it and the budget for this project did not allow me to start figuring out why not, so that will be left for a future update.
I don't know how you're handling the locale detection/switch but with JMSI18nRoutingBundle you can do as below.
Add the required bundles to composer.json:
"require": {
...
"jms/i18n-routing-bundle": "1.1.*",
"jms/translation-bundle": "1.1.*",
"friendsofsymfony/user-bundle": "1.3.*"
},
Configure the bundles:
jms_i18n_routing:
default_locale: en
locales: [en, fr, it, sp]
strategy: prefix
Bootstrap the bundles:
$bundles = array(
...
new JMS\I18nRoutingBundle\JMSI18nRoutingBundle(),
new FOS\UserBundle\FOSUserBundle(),
);
Modify existing routes to prefix them with the desired locale:
access_control:
# Routes are prefixed by ther user locale.
- { path: ^/[^/]+/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/[^/]+/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/[^/]+/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/[^/]+/admin, role: ROLE_ADMIN }
- { path: ^/[^/]+/, role: ROLE_USER }
Now it should work!
My solution: You have to redefine the fos_user routes for the be_simple_i18n type format. (I chose the yaml version):
In app/config/routing.yml
[...]
#register the path to the file with the be_simple_i18n type fos_user routes
fos_user:
resource: "config/routing/fos_user_i18n.yml"
type: be_simple_i18n
my_yaml_i18n_routes:
resource: "config/routing/i18n.yml"
type: be_simple_i18n
In app/Resources/config/routing/fos_user_i18n.yml:
#you have to make entries for all the fos_user routes here!
#you can find them all in vendor/friendsofsymfony/user-bundle/Resources/routing
fos_user_security_login:
locales: { en: "/login", de: "/anmelden" }
defaults: { _controller: FOSUserBundle:Security:login }
fos_user_security_check:
locales: { en: "/login_check", de: "/login_pruefung" }
defaults: { _controller: FOSUserBundle:Security:check }
#...
In app/config/security.yml
firewalls:
[...]
main:
pattern: ^/
form_login:
provider: fos_userbundle
login_path: fos_user_security_login
check_path: fos_user_security_check
csrf_provider: security.csrf.token_manager # Use form.csrf_provider instead for Symfony <2.4
logout:
path: fos_user_security_logout
target: #where_no_one_has_gone_before
[...]
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/anmelden$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/registrieren, role: IS_AUTHENTICATED_ANONYMOUSLY }
[...]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With