diff --git a/web/pgadmin/__init__.py b/web/pgadmin/__init__.py index 1a1432515..1054bde01 100644 --- a/web/pgadmin/__init__.py +++ b/web/pgadmin/__init__.py @@ -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 ########################################################################## diff --git a/web/pgadmin/browser/__init__.py b/web/pgadmin/browser/__init__.py index 18c7fbda4..c8016237f 100644 --- a/web/pgadmin/browser/__init__.py +++ b/web/pgadmin/browser/__init__.py @@ -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 diff --git a/web/pgadmin/browser/server_groups/servers/roles/templates/role/js/role.js b/web/pgadmin/browser/server_groups/servers/roles/templates/role/js/role.js index cbda5b7f2..a85416cd9 100644 --- a/web/pgadmin/browser/server_groups/servers/roles/templates/role/js/role.js +++ b/web/pgadmin/browser/server_groups/servers/roles/templates/role/js/role.js @@ -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() { diff --git a/web/pgadmin/browser/server_groups/servers/types.py b/web/pgadmin/browser/server_groups/servers/types.py index 02c04d699..9a82ac463 100644 --- a/web/pgadmin/browser/server_groups/servers/types.py +++ b/web/pgadmin/browser/server_groups/servers/types.py @@ -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): diff --git a/web/pgadmin/browser/server_groups/templates/server_groups/server_groups.js b/web/pgadmin/browser/server_groups/templates/server_groups/server_groups.js index 39409a724..bbb657510 100644 --- a/web/pgadmin/browser/server_groups/templates/server_groups/server_groups.js +++ b/web/pgadmin/browser/server_groups/templates/server_groups/server_groups.js @@ -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'] } ], diff --git a/web/pgadmin/misc/__init__.py b/web/pgadmin/misc/__init__.py index e88b606a9..80ecd431d 100644 --- a/web/pgadmin/misc/__init__.py +++ b/web/pgadmin/misc/__init__.py @@ -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__) diff --git a/web/pgadmin/preferences/__init__.py b/web/pgadmin/preferences/__init__.py index 9b7b36274..502009eb0 100644 --- a/web/pgadmin/preferences/__init__.py +++ b/web/pgadmin/preferences/__init__.py @@ -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 + diff --git a/web/pgadmin/preferences/templates/preferences/preferences.js b/web/pgadmin/preferences/templates/preferences/preferences.js index 399ab0151..453d20726 100644 --- a/web/pgadmin/preferences/templates/preferences/preferences.js +++ b/web/pgadmin/preferences/templates/preferences/preferences.js @@ -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'; diff --git a/web/pgadmin/static/css/pgadmin.css b/web/pgadmin/static/css/pgadmin.css index 9729d51f8..67e8b4104 100644 --- a/web/pgadmin/static/css/pgadmin.css +++ b/web/pgadmin/static/css/pgadmin.css @@ -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; +} \ No newline at end of file diff --git a/web/pgadmin/templates/security/login_user.html b/web/pgadmin/templates/security/login_user.html index 259c1b08f..1eeee6159 100644 --- a/web/pgadmin/templates/security/login_user.html +++ b/web/pgadmin/templates/security/login_user.html @@ -3,10 +3,21 @@ {% block panel_body %}
{{ _('Forgotten your password?', url=url_for('security.forgot_password')) }} diff --git a/web/pgadmin/utils/preferences.py b/web/pgadmin/utils/preferences.py index e0da6c893..932351dc9 100644 --- a/web/pgadmin/utils/preferences.py +++ b/web/pgadmin/utils/preferences.py @@ -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(