Repository: django-cms/django-cms

Issue:
French gettext translation does not work in 3.0.9 and 3.0.8
Hey there, 
I generated a new site with the awesome [djangocms-installer](https://github.com/nephila/djangocms-installer) tool and realised after a while that django-cms is not being translated to the user's language. 
## Steps to reproduce:

```
$ pip install --upgrade virtualenv
$ virtualenv env
$ source env/bin/activate
(env) $ pip install djangocms-installer
(env) $ djangocms -p . omg
Database configuration (in URL format) [default sqlite://localhost/project.db]:
django CMS version (choices: 2.4, 3.0, stable, develop) [default stable]:
Django version (choices: 1.4, 1.5, 1.6, 1.7, stable) [default stable]:
Activate Django I18N / L10N setting (choices: yes, no) [default yes]:
Install and configure reversion support (choices: yes, no) [default yes]:
Languages to enable. Option can be provided multiple times, or as a comma separated list. Only language codes supported by Django can be used here: fr, en
Optional default time zone [default America/Chicago]:
Activate Django timezone support (choices: yes, no) [default yes]:
Activate CMS permission management (choices: yes, no) [default yes]:
Use Twitter Bootstrap Theme (choices: yes, no) [default no]:
Use custom template set [default no]:
Load a starting page with examples after installation. Choose "no" if you use a custom template set. (choices: yes, no) [default no]: yes
```

As you can see, I've used most of the defaults and djangocms is not using french, but everything else does. Note the order of the languages; **_fr, en**_. Tell me if I'm wrong, but I think this sets the main language to french and gives user's the ability to translate content in english too.
## Generated `settings.py`:

**note that `SECRET_KEY` you see here is not being used anywhere** ;)

```
import os
gettext = lambda s: s
DATA_DIR = os.path.dirname(os.path.dirname(__file__))
"""
Django settings for omg project.

For more information on this file, see
https://docs.djangoproject.com/en/1.6/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.6/ref/settings/
"""

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.6/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '@j#r%*#u&2v!yxih1n11e)4gg%k+)1bm&=mdhdcpzn9#ptn597'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

TEMPLATE_DEBUG = True

ALLOWED_HOSTS = []


# Application definition





ROOT_URLCONF = 'omg.urls'

WSGI_APPLICATION = 'omg.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.6/ref/settings/#databases



# Internationalization
# https://docs.djangoproject.com/en/1.6/topics/i18n/

LANGUAGE_CODE = 'fr'

TIME_ZONE = 'America/Chicago'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.6/howto/static-files/

STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(DATA_DIR, 'media')
STATIC_ROOT = os.path.join(DATA_DIR, 'static')

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'omg', 'static'),
)
SITE_ID = 1

TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.Loader',
    'django.template.loaders.app_directories.Loader',
    'django.template.loaders.eggs.Loader'
)

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.middleware.doc.XViewMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'cms.middleware.user.CurrentUserMiddleware',
    'cms.middleware.page.CurrentPageMiddleware',
    'cms.middleware.toolbar.ToolbarMiddleware',
    'cms.middleware.language.LanguageCookieMiddleware'
)

TEMPLATE_CONTEXT_PROCESSORS = (
    'django.contrib.auth.context_processors.auth',
    'django.contrib.messages.context_processors.messages',
    'django.core.context_processors.i18n',
    'django.core.context_processors.debug',
    'django.core.context_processors.request',
    'django.core.context_processors.media',
    'django.core.context_processors.csrf',
    'django.core.context_processors.tz',
    'sekizai.context_processors.sekizai',
    'django.core.context_processors.static',
    'cms.context_processors.cms_settings'
)

TEMPLATE_DIRS = (
    os.path.join(BASE_DIR, 'omg', 'templates'),
)

INSTALLED_APPS = (
    'djangocms_admin_style',
    'djangocms_text_ckeditor',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.admin',
    'django.contrib.sites',
    'django.contrib.sitemaps',
    'django.contrib.staticfiles',
    'django.contrib.messages',
    'cms',
    'menus',
    'sekizai',
    'mptt',
    'djangocms_style',
    'djangocms_column',
    'djangocms_file',
    'djangocms_flash',
    'djangocms_googlemap',
    'djangocms_inherit',
    'djangocms_link',
    'djangocms_picture',
    'djangocms_teaser',
    'djangocms_video',
    'south',
    'reversion',
    'omg'
)

LANGUAGES = (
    ## Customize this
    ('fr', gettext('fr')),
    ('en', gettext('en')),
)

CMS_LANGUAGES = {
    ## Customize this
    'default': {
        'public': True,
        'hide_untranslated': False,
        'redirect_on_fallback': True,
    },
    1: [
        {
            'public': True,
            'code': 'fr',
            'hide_untranslated': False,
            'name': gettext('fr'),
            'redirect_on_fallback': True,
        },
        {
            'public': True,
            'code': 'en',
            'hide_untranslated': False,
            'name': gettext('en'),
            'redirect_on_fallback': True,
        },
    ],
}

CMS_TEMPLATES = (
    ## Customize this
    ('fullwidth.html', 'Fullwidth'),
    ('sidebar_left.html', 'Sidebar Left'),
    ('sidebar_right.html', 'Sidebar Right')
)

CMS_PERMISSION = True

CMS_PLACEHOLDER_CONF = {}

DATABASES = {
    'default':
        {'ENGINE': 'django.db.backends.sqlite3', 'NAME': 'project.db', 'HOST': 'localhost', 'USER': '', 'PASSWORD': '', 'PORT': ''}
}
```

Maybe this has something to do with djangocms-installer directly. I first asked a [question on stackoverflow](http://stackoverflow.com/questions/28140779/django-cms-not-using-users-language-for-its-core-translations) about this, it contains a bit more infos and screenshots.



Discussion:
Apparently there is something wrong with the french translations in django CMS
Any other language combination looks fine
Could you try downgrading to django CMS 3.0.7? (`pip install django-cms==3.0.7`)

You are right, I just tested with previous versions and it works fine with `django-cms==3.0.7`.

It is broken in `django-cms==3.0.8` and `django-cms==3.0.9`

Thanks for checking. Will change the title for this issue 

Here's what I've discovered so far. It appears that when you use the User settings > Language setting, it changes the **Django** setting just fine, but you won't see any difference, because it doesn't actually refresh the whole window. If you refresh the whole _window_, you'll notice that the toolbar changes to the selected language. At this point, if you use the User settings > Language function again to select the same language you selected above, it will actually work.

I see exactly the same behaviour all the way back to 3.0.3 as well, possibly further back.

At this time, it seems the steps:
1. Change language
2. Reload whole page
3. Change language again

Works repeatably.


Resolving patch:
diff --git a/cms/admin/settingsadmin.py b/cms/admin/settingsadmin.py
--- a/cms/admin/settingsadmin.py
+++ b/cms/admin/settingsadmin.py
@@ -1,15 +1,17 @@
 # -*- coding: utf-8 -*-
+
+import json
 from functools import update_wrapper
-from cms.utils.urlutils import admin_reverse
-from django.http import HttpResponseRedirect, HttpResponse
-from django.contrib.auth.admin import csrf_protect_m
-from django.contrib.admin import ModelAdmin
 
 from django.contrib import admin
+from django.contrib.admin import ModelAdmin
+from django.contrib.auth.admin import csrf_protect_m
+from django.http import HttpResponseRedirect, HttpResponse
+from django.utils.translation import override
 
 from cms.models import UserSettings
-import json
 from cms.utils.transaction import wrap_transaction
+from cms.utils.urlutils import admin_reverse
 
 
 class SettingsAdmin(ModelAdmin):
@@ -58,15 +60,34 @@ def session_store(self, request):
         if request.method == "POST":
             request.session['cms_settings'] = request.POST['settings']
             request.session.save()
-        return HttpResponse(json.dumps(request.session.get('cms_settings', '')), mimetype="application/json")
+        return HttpResponse(
+            json.dumps(request.session.get('cms_settings', '')),
+            mimetype="application/json"
+        )
 
     def save_model(self, request, obj, form, change):
         obj.user = request.user
         obj.save()
 
     def response_post_save_change(self, request, obj):
-        post_url = admin_reverse('index', current_app=self.admin_site.name)
-        return HttpResponseRedirect(post_url)
+        #
+        # When the user changes his language setting, we need to do two things:
+        # 1. Change the language-prefix for the sideframed admin view
+        # 2. Reload the whole window so that the new language affects the
+        #    toolbar, etc.
+        #
+        # To do this, we first redirect the sideframe to the correct new, URL,
+        # but we pass a GET param 'reload_window', which instructs JS on that
+        # page to strip (to avoid infinite redirection loops) that param then
+        # reload the whole window again.
+        #
+        with override(obj.language):
+            post_url = admin_reverse(
+                'cms_usersettings_change',
+                args=[obj.id, ],
+                current_app=self.admin_site.name
+            )
+        return HttpResponseRedirect("{0}?reload_window".format(post_url))
 
     def has_change_permission(self, request, obj=None):
         if obj and obj.user == request.user:


Test patch: