Closed damien-roche closed 12 years ago
The locale is automatically set, however only under certain conditions when you set it before the Routercontext object is created by the Routing Listener.
@Fabien: That reminds me we should make the Locale an object with __toString() so that you can change it without having to hax0r the RouterContext aswell.
On Thu, 14 Jul 2011 23:57:58 -0700 ivrock reply@reply.github.com wrote:
Personally I think it should be supported by default, only having to specify locale to override.
For example if I have routes:
/contact /about
/fr/contact /fr/about
on /fr/about I have a path:
{{ path('contact') }}
Why would that create a path for /contact by default instead of /fr/contact ?
From what I understand to create what should be default behavior on a per link basis, I must:
{{ path('address', {'_locale': app.request.attributes.get('_locale')}) }}
Any plans to amend this?
Reply to this email directly or view it on GitHub: https://github.com/symfony/symfony/issues/1700
Hmm..
What about this situation? We have a default application in english and so no /en/ prefix. All routes automatically have /en/ prefix inserted which is causing inconsistencies with url structure. Is there any way to bypass that so if default locale is active then no prefix is used on the routes?
@ivrock: This is exactly the behavior I'm also looking for - having the URL for routes with default locale not contain the locale parameter at all. That would even allow an application to be initially extended with support for locales without breaking all old URLs around in email notifications, bookmarks, etc. Although when asking about this in IRC I was told that this would not be possible (and I'm still wondering why).
@beberlei: You mean @fabpot, right? ;)
@craue: The only viable solutions I can see in the mean time is to:
Did they give any reason as to why that isn't possible?
@ivrock: Yes, someone had given an example. It's not explicitly about locales but hiding parameters with default values from the URL. Remainder of this comment is quoting http://pastebin.com/gavYkF0C :
foo:
pattern: /foo/{bar}/{car}
defaults:
bar: barValue
car: carValue
Generate a route in a controller:
$this->get('router')->generate('foo', array('bar' => 'barValue', 'car' => 'somethingElse');
In your scenario where a default value is hidden from the url 'barValue' would NOT be added to the url because it matches the default value so the generated url would be: /foo/somethingElse
Now if someone clicked that link and requested /foo/somethingElse and it happened to match the foo route then it would be the equivalent of /foo/somethingElse/carValue
The bar and car param has been mixed up.
Thanks, that should help!
Although, that is only one half. How about doing the same in the twig templates? (see original message). It would seem I have to extend the path() function to automatically include the default locale if that is the current locale.
@ivrock: Sure that's possible (see https://github.com/craue/TwigExtensionsBundle/blob/92ef57f757a24493314c0029d3e21c6ee5563d05/Twig/Extension/ChangeLanguageExtension.php#L223) ;), but doesn't look like the solution to me.
@ivrock: Based on your initial description you are defining all routes twice? Those without locale prefix (for the default locale) on the one hand and those locale-prefixed on the other hand? I tried that by importing the routing config file twice which results in duplicate defined route names, of course. What would be a good solution?
Hi. No, that is what I'm trying to avoid. If I have 10 languages suddenly I have hundreds of routes, where 10 would suffice.
Although that seems like a decent idea if I only have a few languages.
I currently have:
app.com/fr/contact app.com/en/contact
where /en/ is default locale for the application. So I want the route
app.com/contact
To work as /en/ automatically. At the moment I have to create another route which doesn't contain locale, and when you are on this default locale all path() routes generated for twig template include that locale.
A solution to that would be great.
I should clarify exactly what output I'm looking for.
I have:
pattern: /{locale}/contact
I want the routes:
app.com/contact (default locale set in config file) app.com/fr/contact
Now, when I'm viewing app.com/contact, I want the path() in twig to not include /{locale}/pagename because all my routes should default to /pagename.
The 2 roadblocks to this are:
If I use more than 1 path to create /contact as well then I have an even bigger problem: path() requires the path param, yet I have now have 2 depending on the locale.
path('contact') path('contactIN')
It all seems very messy. Even if I extend twig to remove locale if default locale selected on path(), I still have problem with routes not working. Appreciate any ideas, though I suspect this isn't possible as is right now.
@ivrock: You should use the (kind of) "magic" parameter {_locale}
instead of {locale}
which means you would have to define all routes exactly twice as I mentioned, not one branch for each locale. But the problem you described persists and I also doubt there's a clean solution for that currently.
Sorry, I didn't know there was a difference. I use {_locale}, just used {locale} for the example, and yes, sadly, problem still persists.
Hi,
I'm using the {_locale}
parameter with a defaults for this parameter to achieve what you want. I'm using annotations but I don't see why it could not work using a YAML routing file. Here some info.
Say I have the following paths I want to support:
app.com/
=> (should be in english)
app.com/en
=> (should be in english)
app.com/fr
=> (should be in french)
I achieve this with the following annotations in my controller:
/**
* @Route("/{_locale}", name = "index", defaults = {"_locale" = "en"})
*/
I did not set any requirements because for now, it is not possible to use parameters in routing definition so adding a new locale would mean changing a lots of requirements clauses. This is also true for the defaults
clause but changing the default locale is less likely to happen then adding a new locale. Anyway for now, trying to load app.com/es
will output the page in english which is my default locale.
In Twig, I then do {{ path('index') }}
and the url app.com/
will be produced if the current {_locale}
is en
and app.com/fr
will be outputted if the current {_locale}
is fr
. This work event for routes without a default set. For example, with this route:
/**
* @Route("/{_locale}/event/create", name = "event_create")
*/
If a do this in Twig, {{ path('event_create') }}
, the output change in respect to the current value of the parameter {_locale}
.
In en
=> app.com/en/event/create
In fr
=> app.com/fr/event/create
Without me having to specify the locale anywhere.
Hope this helps.
Regards, Matt
I have also faced some problems with this, and you can find my solution here: http://github.com/schmittjoh/JMSI18nRoutingBundle
Basically, you can start without any localized routes, and then add translations for your routes or just for some of them as needed.
Let me know what you think and maybe we can include some of its functionality in Symfony 2.1.
@schmittjoh: Thx, this seems indeed interesting. I'm gonna look at it in the next few days and will give you my feedback about it.
Thanks for your work on this bundle and on Symfony.
Regards, Matt
Hi , maybe this link would help : http://stackoverflow.com/questions/5800675/symfony2-locale-in-route/5803144#5803144
{{ path('address', {'_locale': app.request.attributes.get('_locale')}) }}
In master, the issue described by @beberlei has been fixed (but it's not possible to backport this fix to 2.0). So, the _locale
argument is now always available and you don't need to pass it explicitly when generating a route for the current locale.
For the moment it's possible (and efficient to do this):
PTCIdentialsBundle:
resource: "@PTCIdentialsBundle/Controller/"
type: annotation
prefix: /{_locale}
But it's not possible to add a defaults: { _locale: en }
parameter here. It's only possible when defining the routes for one controller, like this:
contact:
pattern: /{_locale}/contact
defaults: { _controller: AcmeDemoBundle:Contact:index, _locale: en }
requirements:
_locale: en|fr|de
So in order to not have problems when accessing to the root of the site, I need to create a redirect like this:
root:
pattern: /
defaults:
_controller: FrameworkBundle:Redirect:redirect
route: homepage
permanent: true # this is for 301
And for all my routes I always have the locale, even for the defaut locale:
In en
=> http://my-app.com/en
(default locale)
In fr
=> http://my-app.com/fr
It would be more interesting to have the same behavior as if I had added the {_locale} directly on a specific controller:
/**
* @Route("/{_locale}", name = "homepage", defaults = {"_locale" = "en"})
*/
@raziel057 It is possible to defaults when importing when you are using Sf 2.2
I use the last version of Symfony (v 2.2.1) but defaults
has no effect when I write:
PTCIdentialsBundle:
resource: "@PTCIdentialsBundle/Controller/"
type: annotation
prefix: /{_locale}
defaults: { _locale: en }
I can't access to http://my-app.com/
In fact to be accurate, defaults
is taken into account as we can see with router:debug
command
> php app/console router:debug welcome_index
[router] Route "welcome_index"
Name welcome_index
Path /{_locale}/
Host ANY
Scheme ANY
Method ANY
Class Symfony\Component\Routing\Route
Defaults _controller: PTC\IdentialsBundle\Controller\WelcomeController::indexAction
_locale: en
Requirements _locale: en|fr
Options compiler_class: Symfony\Component\Routing\RouteCompiler
Path-Regex #^/(?P<_locale>en|fr)/$#s
But if I try to access http://my-app.com/
, I get a "NotFoundHttpException".
@raziel057 i would try and remove the traling "/" and see if it works.
@henrikbjorn I already tried but it doesn't works.
Moreover, if I have an other route like this:
> php app/console router:debug login
[router] Route "login"
Name login
Path /{_locale}/secured/login
Host ANY
Scheme ANY
Method ANY
Class Symfony\Component\Routing\Route
Defaults _controller: PTC\IdentialsBundle\Controller\AuthenticationController::indexAction
Requirements _locale: en|fr
Options compiler_class: Symfony\Component\Routing\RouteCompiler
Path-Regex #^/(?P<_locale>en|fr)/secured/login$#s
{_locale}/
shoud be replaced by an empty string when accessing in default language in order to have:
http://my-app.com/secured/login
in en
http://my-app.com/fr/secured/login
in fr
@raziel057 you are hitting #4322 when importing a route. The locale is not optional for /{_locale}/
even with a default. So /
does not match. You can see it with the help of the regex.
{_locale}/ shoud be replaced by an empty string when accessing in default language in order to have: http://my-app.com/secured/login in en http://my-app.com/fr/secured/login in fr
The same reason: It's not possible to have optional placeholders in the middle. #7051 would solve it.
@Tobion Ok. Thanks for your explanations. I thought it was possible when reading the comment of @maoueh.
Do you know what is used to display the official documentation of Symfony? http://symfony.com/doc/current/book/forms.html <- content in "en" http://symfony.com/fr/doc/current/book/forms.html <- content in "fr"
Is it this bundle? http://github.com/schmittjoh/JMSI18nRoutingBundle
Don't know. But as a workaround you can define two routes: one with the locale and one without. You just need to chose the approriate one when generating a route.
When I use http://github.com/schmittjoh/JMSI18nRoutingBundle with this configuration:
jms_i18n_routing:
default_locale: en
locales: [en, fr]
strategy: prefix_except_default
I have the following routes when I execute php app/console router:debug
:
en__RG__welcome_index ANY ANY ANY /
fr__RG__welcome_index ANY ANY ANY /fr/
en__RG__view_about ANY ANY ANY /about
fr__RG__view_about ANY ANY ANY /fr/about
en__RG__view_contact ANY ANY ANY /contact
fr__RG__view_contact ANY ANY ANY /fr/contact
...
So we can see that routes are well duplicated. But when I try to access to http://my-app.com/
I got the following error:
FatalErrorException: Error: Maximum function nesting level of '100' reached, aborting! in /home/lallement/workspace/Identials/vendor/symfony/symfony/src/Symfony/Component/Routing/Matcher/Dumper/DumperCollection.php line 54
in /home/lallement/workspace/Identials/vendor/symfony/symfony/src/Symfony/Component/Routing/Matcher/Dumper/DumperCollection.php line 54
at ErrorHandler??handleFatal() in /home/lallement/workspace/Identials/vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Debug/ErrorHandler.php line 0
at DumperCollection??add() in /home/lallement/workspace/Identials/vendor/symfony/symfony/src/Symfony/Component/Routing/Matcher/Dumper/DumperPrefixCollection.php line 70
at DumperPrefixCollection??addPrefixRoute() in /home/lallement/workspace/Identials/vendor/symfony/symfony/src/Symfony/Component/Routing/Matcher/Dumper/DumperPrefixCollection.php line 72
Use the search please.
@Tobion Yes sorry ;). The max_nesting_level
of xdebug was to low.
anyone found a solution to the very first @damien-roche problem? I've exactly the same problem and can't find a clean solution
I'm not sure that this is what you're looking for and after so many years it may not be so useful... but here is what I've done to solve my problem that seems to be pretty similar to the situation described by @damien-roche .
First of all I'm working with version 5.1.2
of Symfony.
Here is my translation.yaml
file:
framework:
default_locale: fr
translator:
default_path: '%kernel.project_dir%/translations'
fallbacks:
- en
enabled_locales: ['fr', 'en']
I defined the supported locales and defined FR
as the default one with a fallback to EN
. This configuration is not part of your routing question but as translations management is also part of my solution to manage a multi-language website, I share it also.
I changed the configuration of my routes so that all defined annotations don't have to be changed for multi-language support, I simply defined a prefix for each supported language in routes/annotations.yaml
:
controllers:
resource: ../../src/Controller/
type: annotation
defaults:
_locale: '%kernel.default_locale%'
requirements:
_locale: fr|en
prefix:
fr: ''
en: '/en'
Then here is what I've configured in security.yaml
to have all my routes working as expected:
access_control:
- { path: ^/(_|en/)login, roles: IS_AUTHENTICATED_ANONYMOUSLY}
- { path: ^/(_|en/)/admin, roles: ROLE_ADMIN}
- { path: ^/(_|en/)/, roles: IS_AUTHENTICATED_ANONYMOUSLY}
This configuration allows me to use all existing routes for my default language (/
, /login
...) and the routes for English version with defined en
prefix (/en
, /en/login
...).
Now when I run php bin/console debug:router
I have all the routes that I can use from my twig templates:
It means that when I simply need to define navigation in my website without worrying about the current locale, I can use my routes as normal:
<a href="{{ path('app_login') }}">{% trans %}action.menu.member.access{% endtrans %}</a>
And when I specifically need to use one of my "localized" routes (for example for the links to switch website from FR to EN), I simply use the appropriate route including the desired locale:
{% if app.request.locale != 'en' %}
<a href="{{ path('app_home_index.en') }}">EN</a>
{% endif %}
{% if app.request.locale != 'fr' %}
<a href="{{ path('app_home_index.fr') }}">FR</a>
{% endif %}
I hope that this will help.
Regards,
If you want to change language in current route You may try this:
{% set routeParams = app.request.attributes.get('_route_params') %}
<a href="{{ path(app.request.attributes.get('_route'), routeParams|merge({'_locale': 'fr'})) }}">FR</a>
Personally I think it should be supported by default, only having to specify locale to override.
For example if I have routes:
/contact /about
/fr/contact /fr/about
on /fr/about I have a path:
{{ path('contact') }}
Why would that create a path for /contact by default instead of /fr/contact ?
From what I understand to create what should be default behavior on a per link basis, I must:
{{ path('address', {'_locale': app.request.attributes.get('_locale')}) }}
Any plans to amend this?