Skip to content
This repository
Browse code

moved management of the locale from the Session class to the Request …

…class

The locale management does not require sessions anymore.

In the Symfony2 spirit, the locale should be part of your URLs. If this is the case
(via the special _locale request attribute), Symfony will store it in the request
(getLocale()).

This feature is now also configurable/replaceable at will as everything is now managed
by the new LocaleListener event listener.

How to upgrade:

The default locale configuration has been moved from session to the main configuration:

Before:

framework:
    session:
        default_locale: en

After:

framework:
    default_locale: en

Whenever you want to get the current locale, call getLocale() on the request (was on the
session before).
  • Loading branch information...
commit 74bc699b270122b70b1de6ece47c726f5df8bd41 1 parent 8b55541
Fabien Potencier authored October 05, 2011

Showing 26 changed files with 264 additions and 152 deletions. Show diff stats Hide diff stats

  1. 1  CHANGELOG-2.1.md
  2. 43  UPGRADE-2.1.md
  3. 2  src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
  4. 3  src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
  5. 63  src/Symfony/Bundle/FrameworkBundle/EventListener/LocaleListener.php
  6. 13  src/Symfony/Bundle/FrameworkBundle/EventListener/RouterListener.php
  7. 2  src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
  8. 1  src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml
  9. 1  src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml
  10. 8  src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml
  11. 10  src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RequestHelper.php
  12. 10  src/Symfony/Bundle/FrameworkBundle/Templating/Helper/SessionHelper.php
  13. 2  src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php
  14. 4  src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml
  15. 2  src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml
  16. 3  src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
  17. 86  src/Symfony/Bundle/FrameworkBundle/Tests/EventListener/LocaleListenerTest.php
  18. 7  src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/RequestHelperTest.php
  19. 7  src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/SessionHelperTest.php
  20. 10  src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php
  21. 2  src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/framework.yml
  22. 30  src/Symfony/Component/HttpFoundation/Request.php
  23. 55  src/Symfony/Component/HttpFoundation/Session.php
  24. 6  src/Symfony/Component/Security/Http/HttpUtils.php
  25. 5  tests/Symfony/Tests/Component/HttpFoundation/RequestMatcherTest.php
  26. 40  tests/Symfony/Tests/Component/HttpFoundation/SessionTest.php
1  CHANGELOG-2.1.md
Source Rendered
@@ -59,6 +59,7 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c
59 59
 
60 60
 ### HttpFoundation
61 61
 
  62
+ * [BC BREAK] moved management of the locale from the Session class to the Request class
62 63
  * added a generic access to the PHP built-in filter mechanism: ParameterBag::filter()
63 64
  * made FileBinaryMimeTypeGuesser command configurable
64 65
  * added Request::getUser() and Request::getPassword()
43  UPGRADE-2.1.md
Source Rendered
@@ -3,11 +3,40 @@ UPGRADE FROM 2.0 to 2.1
3 3
 
4 4
 * assets_base_urls and base_urls merging strategy has changed
5 5
 
6  
-    Unlike most configuration blocks, successive values for
7  
-    ``assets_base_urls`` will overwrite each other instead of being merged.
8  
-    This behavior was chosen because developers will typically define base
9  
-    URL's for each environment. Given that most projects tend to inherit
10  
-    configurations (e.g. ``config_test.yml`` imports ``config_dev.yml``)
11  
-    and/or share a common base configuration (i.e. ``config.yml``), merging
12  
-    could yield a set of base URL's for multiple environments.
  6
+  Unlike most configuration blocks, successive values for
  7
+  ``assets_base_urls`` will overwrite each other instead of being merged.
  8
+  This behavior was chosen because developers will typically define base
  9
+  URL's for each environment. Given that most projects tend to inherit
  10
+  configurations (e.g. ``config_test.yml`` imports ``config_dev.yml``)
  11
+  and/or share a common base configuration (i.e. ``config.yml``), merging
  12
+  could yield a set of base URL's for multiple environments.
13 13
 
  14
+* moved management of the locale from the Session class to the Request class
  15
+
  16
+  Configuring the default locale:
  17
+
  18
+  Before:
  19
+
  20
+      framework:
  21
+        session:
  22
+            default_locale: fr
  23
+
  24
+  After:
  25
+
  26
+      framework:
  27
+        default_locale: fr
  28
+
  29
+  Retrieving the locale from a Twig template:
  30
+
  31
+  Before: {{ app.request.session.locale }}
  32
+  After: {{ app.request.locale }}
  33
+
  34
+  Retrieving the locale from a PHP template:
  35
+
  36
+  Before: $view['session']->getLocale()
  37
+  After: $view['request']->getLocale()
  38
+
  39
+  Retrieving the locale from PHP code:
  40
+
  41
+  Before: $session->getLocale()
  42
+  After: $request->getLocale()
2  src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
@@ -51,6 +51,7 @@ public function getConfigTreeBuilder()
51 51
                 ->scalarNode('secret')->isRequired()->end()
52 52
                 ->scalarNode('ide')->defaultNull()->end()
53 53
                 ->booleanNode('test')->end()
  54
+                ->scalarNode('default_locale')->defaultValue('en')->end()
54 55
             ->end()
55 56
         ;
56 57
 
@@ -161,7 +162,6 @@ private function addSessionSection(ArrayNodeDefinition $rootNode)
161 162
                     ->canBeUnset()
162 163
                     ->children()
163 164
                         ->booleanNode('auto_start')->defaultFalse()->end()
164  
-                        ->scalarNode('default_locale')->defaultValue('en')->end()
165 165
                         ->scalarNode('storage_id')->defaultValue('session.storage.native')->end()
166 166
                         ->scalarNode('name')->end()
167 167
                         ->scalarNode('lifetime')->end()
3  src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
@@ -65,6 +65,8 @@ public function load(array $configs, ContainerBuilder $container)
65 65
 
66 66
         $container->setParameter('kernel.trust_proxy_headers', $config['trust_proxy_headers']);
67 67
 
  68
+        $container->setParameter('kernel.default_locale', $config['default_locale']);
  69
+
68 70
         if (!empty($config['test'])) {
69 71
             $loader->load('test.xml');
70 72
         }
@@ -280,7 +282,6 @@ private function registerSessionConfiguration(array $config, ContainerBuilder $c
280 282
 
281 283
         // session
282 284
         $container->getDefinition('session_listener')->addArgument($config['auto_start']);
283  
-        $container->setParameter('session.default_locale', $config['default_locale']);
284 285
 
285 286
         // session storage
286 287
         $container->setAlias('session.storage', $config['storage_id']);
63  src/Symfony/Bundle/FrameworkBundle/EventListener/LocaleListener.php
... ...
@@ -0,0 +1,63 @@
  1
+<?php
  2
+
  3
+/*
  4
+ * This file is part of the Symfony package.
  5
+ *
  6
+ * (c) Fabien Potencier <fabien@symfony.com>
  7
+ *
  8
+ * For the full copyright and license information, please view the LICENSE
  9
+ * file that was distributed with this source code.
  10
+ */
  11
+
  12
+namespace Symfony\Bundle\FrameworkBundle\EventListener;
  13
+
  14
+use Symfony\Component\HttpKernel\HttpKernelInterface;
  15
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
  16
+use Symfony\Component\Routing\RouterInterface;
  17
+
  18
+/**
  19
+ * Initializes the locale based on the current request.
  20
+ *
  21
+ * @author Fabien Potencier <fabien@symfony.com>
  22
+ */
  23
+class LocaleListener
  24
+{
  25
+    private $router;
  26
+    private $defaultLocale;
  27
+
  28
+    public function __construct($defaultLocale = 'en', RouterInterface $router = null)
  29
+    {
  30
+        $this->defaultLocale = $defaultLocale;
  31
+        $this->router = $router;
  32
+    }
  33
+
  34
+    public function onEarlyKernelRequest(GetResponseEvent $event)
  35
+    {
  36
+        $request = $event->getRequest();
  37
+        if ($request->hasPreviousSession()) {
  38
+            $request->setDefaultLocale($request->getSession()->get('_locale', $this->defaultLocale));
  39
+        } else {
  40
+            $request->setDefaultLocale($this->defaultLocale);
  41
+        }
  42
+    }
  43
+
  44
+    public function onKernelRequest(GetResponseEvent $event)
  45
+    {
  46
+        if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
  47
+            return;
  48
+        }
  49
+
  50
+        $request = $event->getRequest();
  51
+        if ($locale = $request->attributes->get('_locale')) {
  52
+            $request->setLocale($locale);
  53
+
  54
+            if ($request->hasPreviousSession()) {
  55
+                $request->getSession()->set('_locale', $request->getLocale());
  56
+            }
  57
+        }
  58
+
  59
+        if (null !== $this->router) {
  60
+            $this->router->getContext()->setParameter('_locale', $request->getLocale());
  61
+        }
  62
+    }
  63
+}
13  src/Symfony/Bundle/FrameworkBundle/EventListener/RouterListener.php
@@ -88,19 +88,6 @@ public function onKernelRequest(GetResponseEvent $event)
88 88
 
89 89
             throw new MethodNotAllowedHttpException($e->getAllowedMethods(), $message, $e);
90 90
         }
91  
-
92  
-        if (HttpKernelInterface::MASTER_REQUEST === $event->getRequestType()) {
93  
-            $context = $this->router->getContext();
94  
-            $session = $request->getSession();
95  
-            if ($locale = $request->attributes->get('_locale')) {
96  
-                if ($session) {
97  
-                    $session->setLocale($locale);
98  
-                }
99  
-                $context->setParameter('_locale', $locale);
100  
-            } elseif ($session) {
101  
-                $context->setParameter('_locale', $session->getLocale());
102  
-            }
103  
-        }
104 91
     }
105 92
 
106 93
     private function parametersToString(array $parameters)
2  src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
@@ -25,6 +25,7 @@
25 25
         <xsd:attribute name="trust-proxy-headers" type="xsd:string" />
26 26
         <xsd:attribute name="ide" type="xsd:string" />
27 27
         <xsd:attribute name="secret" type="xsd:string" />
  28
+        <xsd:attribute name="default-locale" type="xsd:string" />
28 29
     </xsd:complexType>
29 30
 
30 31
     <xsd:complexType name="form">
@@ -72,7 +73,6 @@
72 73
 
73 74
     <xsd:complexType name="session">
74 75
         <xsd:attribute name="storage-id" type="xsd:string" />
75  
-        <xsd:attribute name="default-locale" type="xsd:string" />
76 76
         <xsd:attribute name="name" type="xsd:string" />
77 77
         <xsd:attribute name="lifetime" type="xsd:integer" />
78 78
         <xsd:attribute name="path" type="xsd:string" />
1  src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml
@@ -14,7 +14,6 @@
14 14
     <services>
15 15
         <service id="session" class="%session.class%">
16 16
             <argument type="service" id="session.storage" />
17  
-            <argument>%session.default_locale%</argument>
18 17
         </service>
19 18
 
20 19
         <service id="session.storage.native" class="%session.storage.native.class%" public="false">
1  src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml
@@ -37,7 +37,6 @@
37 37
                 <argument key="debug">%kernel.debug%</argument>
38 38
                 <argument key="charset">%kernel.charset%</argument>
39 39
             </argument>
40  
-            <argument type="service" id="session" on-invalid="ignore" />
41 40
         </service>
42 41
 
43 42
         <service id="translator" class="%translator.identity.class%">
8  src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml
@@ -8,6 +8,7 @@
8 8
         <parameter key="controller_resolver.class">Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver</parameter>
9 9
         <parameter key="controller_name_converter.class">Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser</parameter>
10 10
         <parameter key="response_listener.class">Symfony\Component\HttpKernel\EventListener\ResponseListener</parameter>
  11
+        <parameter key="locale_listener.class">Symfony\Bundle\FrameworkBundle\EventListener\LocaleListener</parameter>
11 12
     </parameters>
12 13
 
13 14
     <services>
@@ -27,5 +28,12 @@
27 28
             <tag name="kernel.event_listener" event="kernel.response" method="onKernelResponse" />
28 29
             <argument>%kernel.charset%</argument>
29 30
         </service>
  31
+
  32
+        <service id="locale_listener" class="%locale_listener.class%">
  33
+            <tag name="kernel.event_listener" event="kernel.request" method="onEarlyKernelRequest" priority="255" />
  34
+            <tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" priority="-1" />
  35
+            <argument>%kernel.default_locale%</argument>
  36
+            <argument type="service" id="router" on-invalid="ignore" />
  37
+        </service>
30 38
     </services>
31 39
 </container>
10  src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RequestHelper.php
@@ -47,6 +47,16 @@ public function getParameter($key, $default = null)
47 47
     }
48 48
 
49 49
     /**
  50
+     * Returns the locale
  51
+     *
  52
+     * @return string
  53
+     */
  54
+    public function getLocale()
  55
+    {
  56
+        return $this->request->getLocale();
  57
+    }
  58
+
  59
+    /**
50 60
      * Returns the canonical name of this helper.
51 61
      *
52 62
      * @return string The canonical name
10  src/Symfony/Bundle/FrameworkBundle/Templating/Helper/SessionHelper.php
@@ -46,16 +46,6 @@ public function get($name, $default = null)
46 46
         return $this->session->get($name, $default);
47 47
     }
48 48
 
49  
-    /**
50  
-     * Returns the locale
51  
-     *
52  
-     * @return string
53  
-     */
54  
-    public function getLocale()
55  
-    {
56  
-        return $this->session->getLocale();
57  
-    }
58  
-
59 49
     public function getFlash($name, $default = null)
60 50
     {
61 51
         return $this->session->getFlash($name, $default);
2  src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php
@@ -2,6 +2,7 @@
2 2
 
3 3
 $container->loadFromExtension('framework', array(
4 4
     'secret' => 's3cr3t',
  5
+    'default_locale' => 'fr',
5 6
     'form' => null,
6 7
     'csrf_protection' => array(
7 8
         'enabled'    => true,
@@ -19,7 +20,6 @@
19 20
     ),
20 21
     'session' => array(
21 22
         'auto_start'     => true,
22  
-        'default_locale' => 'fr',
23 23
         'storage_id'     => 'session.storage.native',
24 24
         'name'           => '_SYMFONY',
25 25
         'lifetime'       => 86400,
4  src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml
@@ -6,13 +6,13 @@
6 6
     xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd
7 7
                         http://symfony.com/schema/dic/symfony http://symfony.com/schema/dic/symfony/symfony-1.0.xsd">
8 8
 
9  
-    <framework:config secret="s3cr3t" ide="file%%link%%format">
  9
+    <framework:config secret="s3cr3t" ide="file%%link%%format" default-locale="fr">
10 10
         <framework:csrf-protection enabled="true" field-name="_csrf" />
11 11
         <framework:form />
12 12
         <framework:esi enabled="true" />
13 13
         <framework:profiler only-exceptions="true" />
14 14
         <framework:router resource="%kernel.root_dir%/config/routing.xml" type="xml" />
15  
-        <framework:session auto-start="true" default-locale="fr" storage-id="session.storage.native" name="_SYMFONY" lifetime="86400" path="/" domain="example.com" secure="true" httponly="true" />
  15
+        <framework:session auto-start="true" storage-id="session.storage.native" name="_SYMFONY" lifetime="86400" path="/" domain="example.com" secure="true" httponly="true" />
16 16
         <framework:templating assets-version="SomeVersionScheme" cache="/path/to/cache" >
17 17
             <framework:loader>loader.foo</framework:loader>
18 18
             <framework:loader>loader.bar</framework:loader>
2  src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml
... ...
@@ -1,5 +1,6 @@
1 1
 framework:
2 2
     secret: s3cr3t
  3
+    default_locale: fr
3 4
     form: ~
4 5
     csrf_protection:
5 6
         enabled:    true
@@ -13,7 +14,6 @@ framework:
13 14
         type:         xml
14 15
     session:
15 16
         auto_start:     true
16  
-        default_locale: fr
17 17
         storage_id:     session.storage.native
18 18
         name:           _SYMFONY
19 19
         lifetime:       86400
3  src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
@@ -76,8 +76,7 @@ public function testSession()
76 76
         $container = $this->createContainerFromFile('full');
77 77
 
78 78
         $this->assertTrue($container->hasDefinition('session'), '->registerSessionConfiguration() loads session.xml');
79  
-        $this->assertEquals('fr', $container->getParameter('session.default_locale'));
80  
-        $this->assertEquals('%session.default_locale%', $container->getDefinition('session')->getArgument(1));
  79
+        $this->assertEquals('fr', $container->getParameter('kernel.default_locale'));
81 80
         $this->assertTrue($container->getDefinition('session_listener')->getArgument(1));
82 81
         $this->assertEquals('session.storage.native', (string) $container->getAlias('session.storage'));
83 82
 
86  src/Symfony/Bundle/FrameworkBundle/Tests/EventListener/LocaleListenerTest.php
... ...
@@ -0,0 +1,86 @@
  1
+<?php
  2
+
  3
+/*
  4
+ * This file is part of the Symfony package.
  5
+ *
  6
+ * (c) Fabien Potencier <fabien@symfony.com>
  7
+ *
  8
+ * For the full copyright and license information, please view the LICENSE
  9
+ * file that was distributed with this source code.
  10
+ */
  11
+
  12
+namespace Symfony\Bundle\FrameworkBundle\Tests\EventListener;
  13
+
  14
+use Symfony\Bundle\FrameworkBundle\EventListener\LocaleListener;
  15
+use Symfony\Component\HttpFoundation\Request;
  16
+use Symfony\Component\HttpKernel\HttpKernelInterface;
  17
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
  18
+
  19
+class LocaleListenerTest extends \PHPUnit_Framework_TestCase
  20
+{
  21
+    public function testDefaultLocaleWithoutSession()
  22
+    {
  23
+        $listener = new LocaleListener('fr');
  24
+        $event = $this->getEvent($request = Request::create('/'));
  25
+
  26
+        $listener->onEarlyKernelRequest($event);
  27
+        $this->assertEquals('fr', $request->getLocale());
  28
+    }
  29
+
  30
+    public function testDefaultLocaleWithSession()
  31
+    {
  32
+        $request = Request::create('/');
  33
+        session_name('foo');
  34
+        $request->cookies->set('foo', 'value');
  35
+
  36
+        $session = $this->getMock('Symfony\Component\HttpFoundation\Session', array('get'), array(), '', false);
  37
+        $session->expects($this->once())->method('get')->will($this->returnValue('es'));
  38
+        $request->setSession($session);
  39
+
  40
+        $listener = new LocaleListener('fr');
  41
+        $event = $this->getEvent($request);
  42
+
  43
+        $listener->onEarlyKernelRequest($event);
  44
+        $this->assertEquals('es', $request->getLocale());
  45
+    }
  46
+
  47
+    public function testLocaleFromRequestAttribute()
  48
+    {
  49
+        $request = Request::create('/');
  50
+        session_name('foo');
  51
+        $request->cookies->set('foo', 'value');
  52
+
  53
+        $request->attributes->set('_locale', 'es');
  54
+        $listener = new LocaleListener('fr');
  55
+        $event = $this->getEvent($request);
  56
+
  57
+        // also updates the session _locale value
  58
+        $session = $this->getMock('Symfony\Component\HttpFoundation\Session', array('set'), array(), '', false);
  59
+        $session->expects($this->once())->method('set')->with('_locale', 'es');
  60
+        $request->setSession($session);
  61
+
  62
+        $listener->onKernelRequest($event);
  63
+        $this->assertEquals('es', $request->getLocale());
  64
+    }
  65
+
  66
+    public function testLocaleSetForRoutingContext()
  67
+    {
  68
+        // the request context is updated
  69
+        $context = $this->getMock('Symfony\Component\Routing\RequestContext');
  70
+        $context->expects($this->once())->method('setParameter')->with('_locale', 'es');
  71
+
  72
+        $router = $this->getMock('Symfony\Component\Routing\Router', array('getContext'), array(), '', false);
  73
+        $router->expects($this->once())->method('getContext')->will($this->returnValue($context));
  74
+
  75
+        $request = Request::create('/');
  76
+
  77
+        $request->attributes->set('_locale', 'es');
  78
+        $listener = new LocaleListener('fr', $router);
  79
+        $listener->onKernelRequest($this->getEvent($request));
  80
+    }
  81
+
  82
+    private function getEvent(Request $request)
  83
+    {
  84
+        return new GetResponseEvent($this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface'), $request, HttpKernelInterface::MASTER_REQUEST);
  85
+    }
  86
+}
7  src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/RequestHelperTest.php
@@ -39,6 +39,13 @@ public function testGetParameter()
39 39
         $this->assertNull($helper->getParameter('foo'));
40 40
     }
41 41
 
  42
+    public function testGetLocale()
  43
+    {
  44
+        $helper = new RequestHelper($this->request);
  45
+
  46
+        $this->assertEquals('en', $helper->getLocale());
  47
+    }
  48
+
42 49
     public function testGetName()
43 50
     {
44 51
         $helper = new RequestHelper($this->request);
7  src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/SessionHelperTest.php
@@ -60,13 +60,6 @@ public function testGet()
60 60
         $this->assertNull($helper->get('foo'));
61 61
     }
62 62
 
63  
-    public function testGetLocale()
64  
-    {
65  
-        $helper = new SessionHelper($this->request);
66  
-
67  
-        $this->assertEquals('en', $helper->getLocale());
68  
-    }
69  
-
70 63
     public function testGetName()
71 64
     {
72 65
         $helper = new SessionHelper($this->request);
10  src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php
@@ -15,7 +15,6 @@
15 15
 use Symfony\Component\Translation\Loader\LoaderInterface;
16 16
 use Symfony\Component\Translation\MessageSelector;
17 17
 use Symfony\Component\DependencyInjection\ContainerInterface;
18  
-use Symfony\Component\HttpFoundation\Session;
19 18
 use Symfony\Component\Config\ConfigCache;
20 19
 
21 20
 /**
@@ -27,7 +26,6 @@ class Translator extends BaseTranslator
27 26
 {
28 27
     protected $container;
29 28
     protected $options;
30  
-    protected $session;
31 29
     protected $loaderIds;
32 30
 
33 31
     /**
@@ -42,11 +40,9 @@ class Translator extends BaseTranslator
42 40
      * @param MessageSelector    $selector  The message selector for pluralization
43 41
      * @param array              $loaderIds An array of loader Ids
44 42
      * @param array              $options   An array of options
45  
-     * @param Session            $session   A Session instance
46 43
      */
47  
-    public function __construct(ContainerInterface $container, MessageSelector $selector, $loaderIds = array(), array $options = array(), Session $session = null)
  44
+    public function __construct(ContainerInterface $container, MessageSelector $selector, $loaderIds = array(), array $options = array())
48 45
     {
49  
-        $this->session = $session;
50 46
         $this->container = $container;
51 47
         $this->loaderIds = $loaderIds;
52 48
 
@@ -74,8 +70,8 @@ public function __construct(ContainerInterface $container, MessageSelector $sele
74 70
      */
75 71
     public function getLocale()
76 72
     {
77  
-        if (null === $this->locale && null !== $this->session) {
78  
-            $this->locale = $this->session->getLocale();
  73
+        if (null === $this->locale && $this->container->has('request')) {
  74
+            $this->locale = $this->container->get('request')->getLocale();
79 75
         }
80 76
 
81 77
         return $this->locale;
2  src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/framework.yml
@@ -7,8 +7,8 @@ framework:
7 7
     validation:    { enabled: true, enable_annotations: true }
8 8
     form: ~
9 9
     test: ~
  10
+    default_locale: en
10 11
     session:
11  
-        default_locale: en
12 12
         auto_start:     true
13 13
         storage_id:     session.storage.filesystem
14 14
 
30  src/Symfony/Component/HttpFoundation/Request.php
@@ -82,6 +82,8 @@ class Request
82 82
     protected $method;
83 83
     protected $format;
84 84
     protected $session;
  85
+    protected $locale;
  86
+    protected $defaultLocale = 'en';
85 87
 
86 88
     static protected $formats;
87 89
 
@@ -892,6 +894,21 @@ public function setRequestFormat($format)
892 894
         $this->format = $format;
893 895
     }
894 896
 
  897
+    public function setDefaultLocale($locale)
  898
+    {
  899
+        $this->setPhpDefaultLocale($this->defaultLocale = $locale);
  900
+    }
  901
+
  902
+    public function setLocale($locale)
  903
+    {
  904
+        $this->setPhpDefaultLocale($this->locale = $locale);
  905
+    }
  906
+
  907
+    public function getLocale()
  908
+    {
  909
+        return null === $this->locale ? $this->defaultLocale : $this->locale;
  910
+    }
  911
+
895 912
     /**
896 913
      * Checks whether the method is safe or not.
897 914
      *
@@ -1262,4 +1279,17 @@ static protected function initializeFormats()
1262 1279
             'rss'  => array('application/rss+xml'),
1263 1280
         );
1264 1281
     }
  1282
+
  1283
+    private function setPhpDefaultLocale($locale)
  1284
+    {
  1285
+        // if either the class Locale doesn't exist, or an exception is thrown when
  1286
+        // setting the default locale, the intl module is not installed, and
  1287
+        // the call can be ignored:
  1288
+        try {
  1289
+            if (class_exists('Locale', false)) {
  1290
+                \Locale::setDefault($locale);
  1291
+            }
  1292
+        } catch (\Exception $e) {
  1293
+        }
  1294
+    }
1265 1295
 }
55  src/Symfony/Component/HttpFoundation/Session.php
@@ -27,25 +27,19 @@ class Session implements \Serializable
27 27
     protected $attributes;
28 28
     protected $flashes;
29 29
     protected $oldFlashes;
30  
-    protected $locale;
31  
-    protected $defaultLocale;
32 30
     protected $closed;
33 31
 
34 32
     /**
35 33
      * Constructor.
36 34
      *
37  
-     * @param SessionStorageInterface $storage       A SessionStorageInterface instance
38  
-     * @param string                  $defaultLocale The default locale
  35
+     * @param SessionStorageInterface $storage A SessionStorageInterface instance
39 36
      */
40  
-    public function __construct(SessionStorageInterface $storage, $defaultLocale = 'en')
  37
+    public function __construct(SessionStorageInterface $storage)
41 38
     {
42 39
         $this->storage = $storage;
43  
-        $this->defaultLocale = $defaultLocale;
44  
-        $this->locale = $defaultLocale;
45 40
         $this->flashes = array();
46 41
         $this->oldFlashes = array();
47 42
         $this->attributes = array();
48  
-        $this->setPhpDefaultLocale($this->defaultLocale);
49 43
         $this->started = false;
50 44
         $this->closed = false;
51 45
     }
@@ -68,8 +62,6 @@ public function start()
68 62
         if (isset($attributes['attributes'])) {
69 63
             $this->attributes = $attributes['attributes'];
70 64
             $this->flashes = $attributes['flashes'];
71  
-            $this->locale = $attributes['locale'];
72  
-            $this->setPhpDefaultLocale($this->locale);
73 65
 
74 66
             // flag current flash messages to be removed at shutdown
75 67
             $this->oldFlashes = $this->flashes;
@@ -183,7 +175,6 @@ public function clear()
183 175
 
184 176
         $this->attributes = array();
185 177
         $this->flashes = array();
186  
-        $this->setPhpDefaultLocale($this->locale = $this->defaultLocale);
187 178
     }
188 179
 
189 180
     /**
@@ -225,30 +216,6 @@ public function getId()
225 216
     }
226 217
 
227 218
     /**
228  
-     * Returns the locale
229  
-     *
230  
-     * @return string
231  
-     */
232  
-    public function getLocale()
233  
-    {
234  
-        return $this->locale;
235  
-    }
236  
-
237  
-    /**
238  
-     * Sets the locale.
239  
-     *
240  
-     * @param string $locale
241  
-     */
242  
-    public function setLocale($locale)
243  
-    {
244  
-        if (false === $this->started) {
245  
-            $this->start();
246  
-        }
247  
-
248  
-        $this->setPhpDefaultLocale($this->locale = $locale);
249  
-    }
250  
-
251  
-    /**
252 219
      * Gets the flash messages.
253 220
      *
254 221
      * @return array
@@ -356,7 +323,6 @@ public function save()
356 323
         $this->storage->write('_symfony2', array(
357 324
             'attributes' => $this->attributes,
358 325
             'flashes'    => $this->flashes,
359  
-            'locale'     => $this->locale,
360 326
         ));
361 327
     }
362 328
 
@@ -380,26 +346,13 @@ public function __destruct()
380 346
 
381 347
     public function serialize()
382 348
     {
383  
-        return serialize(array($this->storage, $this->defaultLocale));
  349
+        return serialize($this->storage);
384 350
     }
385 351
 
386 352
     public function unserialize($serialized)
387 353
     {
388  
-        list($this->storage, $this->defaultLocale) = unserialize($serialized);
  354
+        $this->storage = unserialize($serialized);
389 355
         $this->attributes = array();
390 356
         $this->started = false;
391 357
     }
392  
-
393  
-    private function setPhpDefaultLocale($locale)
394  
-    {
395  
-        // if either the class Locale doesn't exist, or an exception is thrown when
396  
-        // setting the default locale, the intl module is not installed, and
397  
-        // the call can be ignored:
398  
-        try {
399  
-            if (class_exists('Locale', false)) {
400  
-                \Locale::setDefault($locale);
401  
-            }
402  
-        } catch (\Exception $e) {
403  
-        }
404  
-    }
405 358
 }
6  src/Symfony/Component/Security/Http/HttpUtils.php
@@ -127,11 +127,7 @@ private function resetLocale(Request $request)
127 127
         try {
128 128
             $parameters = $this->router->match($request->getPathInfo());
129 129
 
130  
-            if (isset($parameters['_locale'])) {
131  
-                $context->setParameter('_locale', $parameters['_locale']);
132  
-            } elseif ($session = $request->getSession()) {
133  
-                $context->setParameter('_locale', $session->getLocale());
134  
-            }
  130
+            $context->setParameter('_locale', isset($parameters['_locale']) ? $parameters['_locale'] : $request->getLocale());
135 131
         } catch (\Exception $e) {
136 132
             // let's hope user doesn't use the locale in the path
137 133
         }
5  tests/Symfony/Tests/Component/HttpFoundation/RequestMatcherTest.php
@@ -146,10 +146,7 @@ public function testPathWithLocaleIsNotSupported()
146 146
     {
147 147
         $matcher = new RequestMatcher();
148 148
         $request = Request::create('/en/login');
149  
-
150  
-        $session = new Session(new ArraySessionStorage());
151  
-        $session->setLocale('en');
152  
-        $request->setSession($session);
  149
+        $request->setLocale('en');
153 150
 
154 151
         $matcher->matchPath('^/{_locale}/login$');
155 152
         $this->assertFalse($matcher->matches($request));
40  tests/Symfony/Tests/Component/HttpFoundation/SessionTest.php
@@ -128,34 +128,28 @@ public function testMigrateAndInvalidate()
128 128
 
129 129
     public function testSerialize()
130 130
     {
131  
-        $defaultLocale = 'en';
132  
-        $this->session = new Session($this->storage, $defaultLocale);
  131
+        $this->session = new Session($this->storage);
133 132
 
134  
-        $compare = serialize(array($this->storage, $defaultLocale));
  133
+        $compare = serialize($this->storage);
135 134
 
136 135
         $this->assertSame($compare, $this->session->serialize());
137 136
 
138 137
         $this->session->unserialize($compare);
139 138
 
140  
-        $_defaultLocale = new \ReflectionProperty(get_class($this->session), 'defaultLocale');
141  
-        $_defaultLocale->setAccessible(true);
142  
-
143 139
         $_storage = new \ReflectionProperty(get_class($this->session), 'storage');
144 140
         $_storage->setAccessible(true);
145 141
 
146  
-        $this->assertEquals($_defaultLocale->getValue($this->session), $defaultLocale, 'options match');
147 142
         $this->assertEquals($_storage->getValue($this->session), $this->storage, 'storage match');
148 143
     }
149 144
 
150 145
     public function testSave()
151 146
     {
152 147
         $this->storage = new ArraySessionStorage();
153  
-        $defaultLocale = 'fr';
154  
-        $this->session = new Session($this->storage, $defaultLocale);
  148
+        $this->session = new Session($this->storage);
155 149
         $this->session->set('foo', 'bar');
156 150
 
157 151
         $this->session->save();
158  
-        $compare = array('_symfony2' => array('attributes' => array('foo' => 'bar'), 'flashes' => array(), 'locale' => 'fr'));
  152
+        $compare = array('_symfony2' => array('attributes' => array('foo' => 'bar'), 'flashes' => array()));
159 153
 
160 154
         $r = new \ReflectionObject($this->storage);
161 155
         $p = $r->getProperty('data');
@@ -164,27 +158,6 @@ public function testSave()
164 158
         $this->assertSame($p->getValue($this->storage), $compare);
165 159
     }
166 160
 
167  
-    public function testLocale()
168  
-    {
169  
-        $this->assertSame('en', $this->session->getLocale(), 'default locale is en');
170  
-        $this->assertSame('en', \Locale::getDefault(), '\Locale::getDefault() is en');
171  
-
172  
-        $this->session->setLocale('de');
173  
-        $this->assertSame('de', $this->session->getLocale(), 'locale is de');
174  
-        $this->assertSame('de', \Locale::getDefault(), '\Locale::getDefault() is de');
175  
-
176  
-        $this->session = $this->getSession();
177  
-        $this->session->setLocale('fr');
178  
-        $this->assertSame('fr', $this->session->getLocale(), 'locale is fr');
179  
-        $this->assertSame('fr', \Locale::getDefault(), '\Locale::getDefault() is fr');
180  
-    }
181  
-
182  
-    public function testLocaleAfterClear()
183  
-    {
184  
-        $this->session->clear();
185  
-        $this->assertEquals('en', $this->session->getLocale());
186  
-    }
187  
-
188 161
     public function testGetId()
189 162
     {
190 163
         $this->assertNull($this->session->getId());
@@ -194,9 +167,6 @@ public function testStart()
194 167
     {
195 168
         $this->session->start();
196 169
 
197  
-        $this->assertSame('en', $this->session->getLocale());
198  
-        $this->assertSame('en', \Locale::getDefault());
199  
-
200 170
         $this->assertSame(array(), $this->session->getFlashes());
201 171
         $this->assertSame(array(), $this->session->all());
202 172
     }
@@ -210,7 +180,6 @@ public function testSavedOnDestruct()
210 180
         $expected = array(
211 181
             'attributes'=>array('foo'=>'bar'),
212 182
             'flashes'=>array(),
213  
-            'locale'=>'en'
214 183
         );
215 184
         $saved = $this->storage->read('_symfony2');
216 185
         $this->assertSame($expected, $saved);
@@ -227,7 +196,6 @@ public function testSavedOnDestructAfterManualSave()
227 196
         $expected = array(
228 197
             'attributes'=>array('foo'=>'bar'),
229 198
             'flashes'=>array(),
230  
-            'locale'=>'en'
231 199
         );
232 200
         $saved = $this->storage->read('_symfony2');
233 201
         $this->assertSame($expected, $saved);

2 notes on commit 74bc699

Johannes
Collaborator

The Request doesn't feel like the correct object, a container-scoped context holder would be a better fit imo.

This change has the side-effect that users now have to think about the scope of their services if they need the locale. They cannot just change the dependency from the session to the request, doing that will likely lead to a scope error, and cause some wtfs.

Kris Wallsmith

This is being called before the session listener has a chance to call setSession... therefore this is always returning false.

Matthias Nothhaft

maybe the session should still have the locale setter/getter for BC to keep upgrading easy?

Jordi Boggiano

I currently do app.session.locale which also works fine btw

ouardisoft

yes of course, would you change Session and Locale listener.

Please sign in to comment.
Something went wrong with that request. Please try again.