mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2024-11-30 12:33:52 -06:00
Allow users to select UI language at login or from Preferences rather than unpredictable behaviour from browsers. Fixes #2190
This commit is contained in:
parent
6cb9ece6fd
commit
0eda6033df
@ -14,7 +14,7 @@ import os, sys, time
|
||||
from collections import defaultdict
|
||||
from importlib import import_module
|
||||
|
||||
from flask import Flask, abort, request, current_app
|
||||
from flask import Flask, abort, request, current_app, session
|
||||
from flask_babel import Babel, gettext
|
||||
from flask_htmlmin import HTMLMIN
|
||||
from flask_login import user_logged_in
|
||||
@ -29,6 +29,8 @@ from pgadmin.utils.session import create_session_interface
|
||||
from werkzeug.local import LocalProxy
|
||||
from werkzeug.utils import find_modules
|
||||
|
||||
from pgadmin.utils.preferences import Preferences
|
||||
|
||||
from pgadmin.model import db, Role, Server, ServerGroup, User, Version, Keys
|
||||
|
||||
# If script is running under python3, it will not have the xrange function
|
||||
@ -189,8 +191,29 @@ def create_app(app_name=None):
|
||||
|
||||
@babel.localeselector
|
||||
def get_locale():
|
||||
"""Get the best language for the user."""
|
||||
language = request.accept_languages.best_match(config.LANGUAGES.keys())
|
||||
"""Get the language for the user."""
|
||||
language = 'en'
|
||||
if config.SERVER_MODE is False:
|
||||
# Get the user language preference from the miscellaneous module
|
||||
misc_preference = Preferences.module('miscellaneous', False)
|
||||
if misc_preference:
|
||||
user_languages = misc_preference.preference(
|
||||
'user_language'
|
||||
)
|
||||
if user_languages:
|
||||
language = user_languages.get() or language
|
||||
else:
|
||||
# If language is available in get request then return the same
|
||||
# otherwise check the session or cookie
|
||||
data = request.form
|
||||
if 'language' in data:
|
||||
language = data['language'] or language
|
||||
setattr(session, 'PGADMIN_LANGUAGE', language)
|
||||
elif hasattr(session, 'PGADMIN_LANGUAGE'):
|
||||
language = getattr(session, 'PGADMIN_LANGUAGE', language)
|
||||
elif hasattr(request.cookies, 'PGADMIN_LANGUAGE'):
|
||||
language = getattr(request.cookies, 'PGADMIN_LANGUAGE', language)
|
||||
|
||||
return language
|
||||
|
||||
##########################################################################
|
||||
@ -269,6 +292,27 @@ def create_app(app_name=None):
|
||||
##########################################################################
|
||||
driver.init_app(app)
|
||||
|
||||
##########################################################################
|
||||
# Register language to the preferences after login
|
||||
##########################################################################
|
||||
@user_logged_in.connect_via(app)
|
||||
def register_language(sender, user):
|
||||
# After logged in, set the language in the preferences if we get from
|
||||
# the login page
|
||||
data = request.form
|
||||
if 'language' in data:
|
||||
language = data['language']
|
||||
|
||||
# Set the user language preference
|
||||
misc_preference = Preferences.module('miscellaneous')
|
||||
user_languages = misc_preference.preference(
|
||||
'user_language'
|
||||
)
|
||||
|
||||
if user_languages and language:
|
||||
language = user_languages.set(language)
|
||||
|
||||
|
||||
##########################################################################
|
||||
# Register any local servers we can discover
|
||||
##########################################################################
|
||||
|
@ -11,7 +11,8 @@ import json
|
||||
from abc import ABCMeta, abstractmethod, abstractproperty
|
||||
|
||||
import six
|
||||
from flask import current_app, render_template, url_for, make_response, flash
|
||||
from flask import current_app, render_template, url_for, make_response, flash,\
|
||||
Response, request
|
||||
from flask_babel import gettext
|
||||
from flask_login import current_user
|
||||
from flask_security import login_required
|
||||
@ -473,13 +474,26 @@ def index():
|
||||
|
||||
flash(msg, 'warning')
|
||||
|
||||
return render_template(
|
||||
response = Response(render_template(
|
||||
MODULE_NAME + "/index.html",
|
||||
username=current_user.email,
|
||||
is_admin=current_user.has_role("Administrator"),
|
||||
_=gettext
|
||||
)
|
||||
))
|
||||
|
||||
# Set the language cookie after login, so next time the user will have that
|
||||
# same option at the login time.
|
||||
misc_preference = Preferences.module('miscellaneous')
|
||||
user_languages = misc_preference.preference(
|
||||
'user_language'
|
||||
)
|
||||
language = 'en'
|
||||
if user_languages:
|
||||
language = user_languages.get() or 'en'
|
||||
|
||||
response.set_cookie("PGADMIN_LANGUAGE", language)
|
||||
|
||||
return response
|
||||
|
||||
@blueprint.route("/js/browser.js")
|
||||
@login_required
|
||||
|
@ -252,7 +252,7 @@ function($, _, S, pgAdmin, pgBrowser, alertify, Backform) {
|
||||
multiple: true,
|
||||
tags: true,
|
||||
allowClear: data.disabled ? false : true,
|
||||
placeholder: data.disabled ? "" : "Select members",
|
||||
placeholder: data.disabled ? "" : "{{ _('Select members') }}",
|
||||
width: 'style'
|
||||
}).on("change", function(e) {
|
||||
$(e.target).find(':selected').each(function() {
|
||||
|
@ -45,22 +45,27 @@ class ServerType(object):
|
||||
|
||||
@classmethod
|
||||
def register_preferences(cls):
|
||||
paths = Preferences('paths', _('Paths'))
|
||||
# Introduce inner function as we need to register the preferences after
|
||||
# we get the user language and its translation.
|
||||
def register_paths():
|
||||
paths = Preferences('paths', _('Paths'))
|
||||
|
||||
for key in cls.registry:
|
||||
st = cls.registry[key]
|
||||
default_path = config.DEFAULT_BINARY_PATHS[st.stype] or ""
|
||||
for key in cls.registry:
|
||||
st = cls.registry[key]
|
||||
default_path = config.DEFAULT_BINARY_PATHS[st.stype] or ""
|
||||
|
||||
st.utility_path = paths.register(
|
||||
'bin_paths', st.stype + '_bin_dir',
|
||||
_("{0} Binary Path").format(st.desc),
|
||||
'text', default_path, category_label=_('Binary paths'),
|
||||
help_str=_(
|
||||
"Path to the directory containing the {0} utility programs (pg_dump, pg_restore etc).".format(
|
||||
st.desc
|
||||
st.utility_path = paths.register(
|
||||
'bin_paths', st.stype + '_bin_dir',
|
||||
_("{0} Binary Path").format(st.desc),
|
||||
'text', default_path, category_label=_('Binary paths'),
|
||||
help_str=_(
|
||||
"Path to the directory containing the {0} utility"
|
||||
" programs (pg_dump, pg_restore etc).".format(
|
||||
st.desc
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
return register_paths
|
||||
|
||||
@property
|
||||
def priority(self):
|
||||
|
@ -32,10 +32,10 @@ function($, _, pgAdmin, Backbone) {
|
||||
},
|
||||
schema: [
|
||||
{
|
||||
id: 'id', label: 'ID', type: 'int', group: null,
|
||||
id: 'id', label: '{{ _('ID') }}', type: 'int', group: null,
|
||||
mode: ['properties']
|
||||
},{
|
||||
id: 'name', label:'Name', type: 'text', group: null,
|
||||
id: 'name', label:'{{ _('Name') }}', type: 'text', group: null,
|
||||
mode: ['properties', 'edit', 'create']
|
||||
}
|
||||
],
|
||||
|
@ -13,6 +13,7 @@ import pgadmin.utils.driver as driver
|
||||
from flask import url_for, render_template, Response
|
||||
from flask_babel import gettext as _
|
||||
from pgadmin.utils import PgAdminModule
|
||||
from pgadmin.utils.preferences import Preferences
|
||||
|
||||
import config
|
||||
|
||||
@ -41,6 +42,25 @@ class MiscModule(PgAdminModule):
|
||||
)
|
||||
return stylesheets
|
||||
|
||||
def register_preferences(self):
|
||||
"""
|
||||
Register preferences for this module.
|
||||
"""
|
||||
self.misc_preference = Preferences('miscellaneous', _('Miscellaneous'))
|
||||
|
||||
lang_options = []
|
||||
for lang in config.LANGUAGES:
|
||||
lang_options.append({'label': config.LANGUAGES[lang],
|
||||
'value': lang})
|
||||
|
||||
# Register options for the User language settings
|
||||
language = self.misc_preference.register(
|
||||
'miscellaneous', 'user_language',
|
||||
_("User language"), 'options', 'en',
|
||||
category_label=_('User language'),
|
||||
options=lang_options
|
||||
)
|
||||
|
||||
|
||||
# Initialise the module
|
||||
blueprint = MiscModule(MODULE_NAME, __name__)
|
||||
|
@ -13,7 +13,7 @@ side and for getting/setting preferences.
|
||||
"""
|
||||
|
||||
import simplejson as json
|
||||
from flask import render_template, url_for, Response, request
|
||||
from flask import render_template, url_for, Response, request, session
|
||||
from flask_babel import gettext
|
||||
from flask_login import current_user
|
||||
from flask_security import login_required
|
||||
@ -109,23 +109,28 @@ def preferences(module=None, preference=None):
|
||||
res = []
|
||||
|
||||
def label(p):
|
||||
return p['label']
|
||||
return gettext(p['label'])
|
||||
|
||||
for m in pref:
|
||||
if len(m['categories']):
|
||||
om = {
|
||||
"id": m['id'],
|
||||
"label": m['label'],
|
||||
"label": gettext(m['label']),
|
||||
"inode": True,
|
||||
"open": True,
|
||||
"branch": []
|
||||
}
|
||||
|
||||
for c in m['categories']:
|
||||
for p in c['preferences']:
|
||||
if 'label' in p and p['label'] is not None:
|
||||
p['label'] = gettext(p['label'])
|
||||
if 'help_str' in p and p['help_str'] is not None:
|
||||
p['help_str'] = gettext(p['help_str'])
|
||||
oc = {
|
||||
"id": c['id'],
|
||||
"mid": m['id'],
|
||||
"label": c['label'],
|
||||
"label": gettext(c['label']),
|
||||
"inode": False,
|
||||
"open": False,
|
||||
"preferences": sorted(c['preferences'], key=label)
|
||||
@ -155,4 +160,23 @@ def save(pid):
|
||||
if not res:
|
||||
return internal_server_error(errormsg=msg)
|
||||
|
||||
return success_return()
|
||||
response = success_return()
|
||||
|
||||
# Set cookie & session for language settings.
|
||||
# This will execute every time as could not find the better way to know
|
||||
# that which preference is getting updated.
|
||||
|
||||
misc_preference = Preferences.module('miscellaneous')
|
||||
user_languages = misc_preference.preference(
|
||||
'user_language'
|
||||
)
|
||||
|
||||
language = 'en'
|
||||
if user_languages:
|
||||
language = user_languages.get() or language
|
||||
|
||||
setattr(session, 'PGADMIN_LANGUAGE', language)
|
||||
response.set_cookie("PGADMIN_LANGUAGE", language)
|
||||
|
||||
return response
|
||||
|
||||
|
@ -219,7 +219,11 @@ define(
|
||||
var opts = [];
|
||||
// Convert the array to SelectControl understandable options.
|
||||
_.each(p.options, function(o) {
|
||||
opts.push({'label': o, 'value': o});
|
||||
if('label' in o && 'value' in o){
|
||||
opts.push({'label': o.label, 'value': o.value});
|
||||
} else {
|
||||
opts.push({'label': o, 'value': o});
|
||||
}
|
||||
});
|
||||
p.options = opts;
|
||||
return 'select2';
|
||||
|
@ -767,3 +767,16 @@ lgg-el-container[el=md] .pg-el-lg-8,
|
||||
.show_progress {
|
||||
cursor: progress;
|
||||
}
|
||||
.user-language {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.user-language label{
|
||||
float:left;
|
||||
font-weight: normal !important;
|
||||
}
|
||||
.user-language div{
|
||||
float:left;
|
||||
}
|
||||
.user-language select{
|
||||
height: 25px !important;
|
||||
}
|
@ -3,10 +3,21 @@
|
||||
{% block panel_body %}
|
||||
<form action="{{ url_for_security('login') }}" method="POST" name="login_user_form">
|
||||
{{ login_user_form.hidden_tag() }}
|
||||
{% set user_language = request.cookies.get('PGADMIN_LANGUAGE') or 'en' %}
|
||||
<fieldset>
|
||||
{{ render_field_with_errors(login_user_form.email, "text") }}
|
||||
{{ render_field_with_errors(login_user_form.password, "password") }}
|
||||
<input class="btn btn-lg btn-success btn-block" type="submit" value="{{ _('Login') }}">
|
||||
<div class="pgadmin-control-group form-group pg-el-xs-12 user-language">
|
||||
<label class="help-block pg-el-sm-3">{{ _("Language") }}</label>
|
||||
<div class="pgadmin-controls pg-el-sm-9">
|
||||
<select class="form-control" name="language" value="{{user_language}}">
|
||||
{% for key, lang in config.LANGUAGES.items() %}
|
||||
<option value="{{key}}" {% if user_language == key %}selected{% endif %}>{{lang}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
<span class="help-block">{{ _('Forgotten your <a href="%(url)s">password</a>?', url=url_for('security.forgot_password')) }}</span>
|
||||
|
@ -126,8 +126,9 @@ class _Preference(object):
|
||||
current_app.logger.exeception(e)
|
||||
return self.default
|
||||
if self._type == 'options':
|
||||
if res.value in self.options:
|
||||
return res.value
|
||||
for opt in self.options:
|
||||
if 'value' in opt and opt['value'] == res.value:
|
||||
return res.value
|
||||
return self.default
|
||||
if self._type == 'text':
|
||||
if res.value == '':
|
||||
@ -184,7 +185,12 @@ class _Preference(object):
|
||||
current_app.logger.exeception(e)
|
||||
return False, gettext("Invalid value for a datetime option.")
|
||||
elif self._type == 'options':
|
||||
if value not in self.options:
|
||||
has_value = False
|
||||
for opt in self.options:
|
||||
if 'value' in opt and opt['value'] == value:
|
||||
has_value = True
|
||||
|
||||
if not has_value:
|
||||
return False, gettext("Invalid value for an options option.")
|
||||
|
||||
pref = UserPrefTable.query.filter_by(
|
||||
|
Loading…
Reference in New Issue
Block a user