[#1959] [WebUI] Allow user selectable GUI language

This commit is contained in:
bendikro 2016-04-23 22:18:55 +02:00 committed by Calum Lind
parent 74f2f45fc0
commit 857e2fd46e
16 changed files with 227 additions and 110 deletions

View File

@ -10,7 +10,6 @@
"""Common functions for various parts of Deluge to use.""" """Common functions for various parts of Deluge to use."""
import base64 import base64
import gettext
import locale import locale
import logging import logging
import numbers import numbers
@ -903,11 +902,6 @@ def create_localclient_account(append=False):
fd.close() fd.close()
def get_translations_path():
"""Get the absolute path to the directory containing translation files"""
return resource_filename("deluge", "i18n")
def set_env_variable(name, value): def set_env_variable(name, value):
''' '''
:param name: environment variable name :param name: environment variable name
@ -970,75 +964,6 @@ def set_env_variable(name, value):
log.debug('Set Env Var \'%s\' to \'%s\' (\'%s._putenv\')', name, value, msvcrtname) log.debug('Set Env Var \'%s\' to \'%s\' (\'%s._putenv\')', name, value, msvcrtname)
def set_language(lang):
"""
Set the language to use.
gettext and GtkBuilder will load the translations from the specified
language.
:param lang: the language, e.g. "en", "de" or "en_GB"
:type lang: str
"""
lang = str(lang)
# Necessary to set these environment variables for GtkBuilder
set_env_variable('LANGUAGE', lang) # Windows/Linux
set_env_variable('LANG', lang) # For OSX
translations_path = get_translations_path()
try:
ro = gettext.translation("deluge", localedir=translations_path, languages=[lang])
ro.install()
except IOError as ex:
log.warn("IOError when loading translations: %s", ex)
# Initialize gettext
def setup_translations(setup_gettext=True, setup_pygtk=False):
translations_path = get_translations_path()
domain = "deluge"
log.info("Setting up translations from %s", translations_path)
if setup_pygtk:
try:
log.info("Setting up GTK translations from %s", translations_path)
if windows_check():
import ctypes
libintl = ctypes.cdll.intl
libintl.bindtextdomain(domain, translations_path.encode(sys.getfilesystemencoding()))
libintl.textdomain(domain)
libintl.bind_textdomain_codeset(domain, "UTF-8")
libintl.gettext.restype = ctypes.c_char_p
# Use glade for plugins that still uses it
import gtk
import gtk.glade
gtk.glade.bindtextdomain(domain, translations_path)
gtk.glade.textdomain(domain)
except Exception as ex:
log.error("Unable to initialize glade translation!")
log.exception(ex)
if setup_gettext:
try:
if hasattr(locale, "bindtextdomain"):
locale.bindtextdomain(domain, translations_path)
if hasattr(locale, "textdomain"):
locale.textdomain(domain)
gettext.bindtextdomain(domain, translations_path)
gettext.bind_textdomain_codeset(domain, 'UTF-8')
gettext.textdomain(domain)
gettext.install(domain, translations_path, unicode=True)
except Exception as ex:
log.error("Unable to initialize gettext/locale!")
log.exception(ex)
import __builtin__
__builtin__.__dict__["_"] = lambda x: x
translate_size_units()
def unicode_argv(): def unicode_argv():
""" Gets sys.argv as list of unicode objects on any platform.""" """ Gets sys.argv as list of unicode objects on any platform."""
if windows_check(): if windows_check():

View File

@ -17,6 +17,7 @@ import deluge.common
import deluge.configmanager import deluge.configmanager
import deluge.error import deluge.error
from deluge.ui.baseargparser import BaseArgParser from deluge.ui.baseargparser import BaseArgParser
from deluge.ui.util import lang
def add_daemon_options(parser): def add_daemon_options(parser):
@ -55,7 +56,7 @@ def start_daemon(skip_start=False):
deluge.core.daemon.Daemon: A new daemon object deluge.core.daemon.Daemon: A new daemon object
""" """
deluge.common.setup_translations() lang.set_dummy_trans()
# Setup the argument parser # Setup the argument parser
parser = BaseArgParser() parser = BaseArgParser()

View File

@ -6,11 +6,11 @@ from twisted.internet import defer, protocol, reactor
from twisted.internet.defer import Deferred from twisted.internet.defer import Deferred
from twisted.internet.error import CannotListenError from twisted.internet.error import CannotListenError
import deluge.common
import deluge.configmanager import deluge.configmanager
import deluge.core.preferencesmanager import deluge.core.preferencesmanager
import deluge.log import deluge.log
from deluge.error import DelugeError from deluge.error import DelugeError
from deluge.ui.util import lang
deluge.log.setup_logger("none") deluge.log.setup_logger("none")
@ -44,7 +44,7 @@ def rpath(*args):
return os.path.join(os.path.dirname(__file__), *args) return os.path.join(os.path.dirname(__file__), *args)
# Initialize gettext # Initialize gettext
deluge.common.setup_translations() lang.setup_translations()
class ProcessOutputHandler(protocol.ProcessProtocol): class ProcessOutputHandler(protocol.ProcessProtocol):

View File

@ -3,12 +3,13 @@ import os
from twisted.trial import unittest from twisted.trial import unittest
from deluge.common import (VersionSplit, fdate, fpcnt, fpeer, fsize, fspeed, ftime, get_path_size, is_ip, is_magnet, from deluge.common import (VersionSplit, fdate, fpcnt, fpeer, fsize, fspeed, ftime, get_path_size, is_ip, is_magnet,
is_url, setup_translations) is_url)
from deluge.ui.util import lang
class CommonTestCase(unittest.TestCase): class CommonTestCase(unittest.TestCase):
def setUp(self): # NOQA def setUp(self): # NOQA
setup_translations() lang.setup_translations()
def tearDown(self): # NOQA def tearDown(self): # NOQA
pass pass

View File

@ -1,9 +1,9 @@
import pytest import pytest
from twisted.trial import unittest from twisted.trial import unittest
import deluge.common
import deluge.component as component import deluge.component as component
from deluge.configmanager import ConfigManager from deluge.configmanager import ConfigManager
from deluge.ui.util import lang
from . import common from . import common
from .basetest import BaseTestCase from .basetest import BaseTestCase
@ -20,7 +20,7 @@ except ImportError as err:
import traceback import traceback
traceback.print_exc() traceback.print_exc()
deluge.common.setup_translations() lang.setup_translations()
@pytest.mark.gtkui @pytest.mark.gtkui

View File

@ -1,9 +1,9 @@
import pytest import pytest
from twisted.trial import unittest from twisted.trial import unittest
import deluge.common
import deluge.component as component import deluge.component as component
from deluge.configmanager import ConfigManager from deluge.configmanager import ConfigManager
from deluge.ui.util import lang
from . import common from . import common
from .basetest import BaseTestCase from .basetest import BaseTestCase
@ -23,7 +23,7 @@ except ImportError as err:
import traceback import traceback
traceback.print_exc() traceback.print_exc()
deluge.common.setup_translations() lang.setup_translations()
@pytest.mark.gtkui @pytest.mark.gtkui

View File

@ -55,6 +55,7 @@ from deluge.ui.gtkui.torrentview import TorrentView
from deluge.ui.sessionproxy import SessionProxy from deluge.ui.sessionproxy import SessionProxy
from deluge.ui.tracker_icons import TrackerIcons from deluge.ui.tracker_icons import TrackerIcons
from deluge.ui.ui import UI from deluge.ui.ui import UI
from deluge.ui.util import lang
gobject.set_prgname("deluge") gobject.set_prgname("deluge")
@ -163,7 +164,7 @@ class Gtk(UI):
class GtkUI(object): class GtkUI(object):
def __init__(self, args): def __init__(self, args):
# Setup gtkbuilder/glade translation # Setup gtkbuilder/glade translation
deluge.common.setup_translations(setup_gettext=False, setup_pygtk=True) lang.setup_translations(setup_gettext=False, setup_pygtk=True)
# Setup signals # Setup signals
def on_die(*args): def on_die(*args):
@ -201,7 +202,7 @@ class GtkUI(object):
# Set language # Set language
if self.config["language"] is not None: if self.config["language"] is not None:
deluge.common.set_language(self.config["language"]) lang.set_language(self.config["language"])
# Start the IPC Interface before anything else.. Just in case we are # Start the IPC Interface before anything else.. Just in case we are
# already running. # already running.

View File

@ -23,6 +23,7 @@ from deluge.ui.client import client
from deluge.ui.gtkui.common import associate_magnet_links, get_deluge_icon from deluge.ui.gtkui.common import associate_magnet_links, get_deluge_icon
from deluge.ui.gtkui.dialogs import AccountDialog, ErrorDialog, InformationDialog, YesNoDialog from deluge.ui.gtkui.dialogs import AccountDialog, ErrorDialog, InformationDialog, YesNoDialog
from deluge.ui.gtkui.path_chooser import PathChooser from deluge.ui.gtkui.path_chooser import PathChooser
from deluge.ui.util import lang
pygtk.require('2.0') pygtk.require('2.0')
@ -203,21 +204,13 @@ class Preferences(component.Component):
self.copy_torrents_to_hbox.show_all() self.copy_torrents_to_hbox.show_all()
def load_languages(self): def load_languages(self):
from deluge.ui import languages # Import here so that gettext has been setup first
translations_path = deluge.common.get_translations_path()
for root, dirs, files in os.walk(translations_path):
# Get the dirs
lang_dirs = dirs
break
self.language_combo = self.builder.get_object("combobox_language") self.language_combo = self.builder.get_object("combobox_language")
self.language_checkbox = self.builder.get_object("checkbutton_language") self.language_checkbox = self.builder.get_object("checkbutton_language")
lang_model = self.language_combo.get_model() lang_model = self.language_combo.get_model()
langs = lang.get_languages()
index = -1 index = -1
for i, lang_code in enumerate(sorted(lang_dirs)): for i, l in enumerate(langs):
name = "%s (Language name missing)" % lang_code lang_code, name = l
if lang_code in languages.LANGUAGES:
name = languages.LANGUAGES[lang_code]
lang_model.append([lang_code, name]) lang_model.append([lang_code, name])
if self.gtkui_config["language"] == lang_code: if self.gtkui_config["language"] == lang_code:
index = i index = i
@ -225,8 +218,10 @@ class Preferences(component.Component):
if self.gtkui_config["language"] is None: if self.gtkui_config["language"] is None:
self.language_checkbox.set_active(True) self.language_checkbox.set_active(True)
self.language_combo.set_visible(False) self.language_combo.set_visible(False)
elif index != -1: else:
self.language_combo.set_active(index) self.language_combo.set_visible(True)
if index != -1:
self.language_combo.set_active(index)
def __del__(self): def __del__(self):
del self.gtkui_config del self.gtkui_config

View File

@ -13,6 +13,7 @@ import deluge.common
import deluge.configmanager import deluge.configmanager
import deluge.log import deluge.log
from deluge.ui.baseargparser import BaseArgParser from deluge.ui.baseargparser import BaseArgParser
from deluge.ui.util import lang
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -27,7 +28,7 @@ class UI(object):
def __init__(self, name="gtk", parser=None): def __init__(self, name="gtk", parser=None):
self.__name = name self.__name = name
deluge.common.setup_translations(setup_pygtk=(name == "gtk")) lang.setup_translations(setup_pygtk=(name == "gtk"))
self.__parser = parser if parser else BaseArgParser() self.__parser = parser if parser else BaseArgParser()
def parse_args(self, args=None): def parse_args(self, args=None):

View File

@ -13,14 +13,15 @@
"""Main starting point for Deluge""" """Main starting point for Deluge"""
import logging
import sys import sys
from logging import getLogger
import pkg_resources import pkg_resources
import deluge.common import deluge.common
import deluge.configmanager import deluge.configmanager
from deluge.ui.baseargparser import BaseArgParser from deluge.ui.baseargparser import BaseArgParser
from deluge.ui.util import lang
DEFAULT_PREFS = { DEFAULT_PREFS = {
"default_ui": "gtk" "default_ui": "gtk"
@ -29,7 +30,7 @@ DEFAULT_PREFS = {
def start_ui(): def start_ui():
"""Entry point for ui script""" """Entry point for ui script"""
deluge.common.setup_translations() lang.setup_translations()
# Setup the argument parser # Setup the argument parser
parser = BaseArgParser() parser = BaseArgParser()
@ -56,7 +57,7 @@ def start_ui():
options = parser.parse_args(deluge.common.unicode_argv()[1:]) options = parser.parse_args(deluge.common.unicode_argv()[1:])
config = deluge.configmanager.ConfigManager("ui.conf", DEFAULT_PREFS) config = deluge.configmanager.ConfigManager("ui.conf", DEFAULT_PREFS)
log = getLogger(__name__) log = logging.getLogger(__name__)
if options.default_ui: if options.default_ui:
config["default_ui"] = options.default_ui config["default_ui"] = options.default_ui

View File

119
deluge/ui/util/lang.py Normal file
View File

@ -0,0 +1,119 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2007,2008 Andrew Resch <andrewresch@gmail.com>
#
# This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with
# the additional special exception to link portions of this program with the OpenSSL library.
# See LICENSE for more details.
#
import gettext
import locale
import logging
import os
import sys
import deluge.common
log = logging.getLogger(__name__)
log.addHandler(logging.NullHandler()) # Silence: No handlers could be found for logger "deluge.util.lang"
def set_dummy_trans(warn_msg=None):
import __builtin__
def _func(txt):
if warn_msg:
log.warn("'%s' has been marked for translation, but translation is unavailable.", txt)
return txt
__builtin__.__dict__["_"] = _func
def get_translations_path():
"""Get the absolute path to the directory containing translation files"""
return deluge.common.resource_filename("deluge", "i18n")
def get_languages():
from deluge.ui import languages # Import here so that gettext has been setup first
translations_path = get_translations_path()
for root, dirs, files in os.walk(translations_path):
# Get the dirs
lang_dirs = dirs
break
lang = []
for i, lang_code in enumerate(sorted(lang_dirs)):
name = "%s (Language name missing)" % lang_code
if lang_code in languages.LANGUAGES:
name = languages.LANGUAGES[lang_code]
lang.append([lang_code, name])
return lang
def set_language(lang):
"""
Set the language to use.
gettext and GtkBuilder will load the translations from the specified
language.
:param lang: the language, e.g. "en", "de" or "en_GB"
:type lang: str
"""
lang = str(lang)
# Necessary to set these environment variables for GtkBuilder
deluge.common.set_env_variable('LANGUAGE', lang) # Windows/Linux
deluge.common.set_env_variable('LANG', lang) # For OSX
translations_path = get_translations_path()
try:
ro = gettext.translation("deluge", localedir=translations_path, languages=[lang])
ro.install()
except IOError as ex:
log.warn("IOError when loading translations: %s", ex)
# Initialize gettext
def setup_translations(setup_gettext=True, setup_pygtk=False):
translations_path = get_translations_path()
domain = "deluge"
log.info("Setting up translations from %s", translations_path)
if setup_pygtk:
try:
log.info("Setting up GTK translations from %s", translations_path)
if deluge.common.windows_check():
import ctypes
libintl = ctypes.cdll.intl
libintl.bindtextdomain(domain, translations_path.encode(sys.getfilesystemencoding()))
libintl.textdomain(domain)
libintl.bind_textdomain_codeset(domain, "UTF-8")
libintl.gettext.restype = ctypes.c_char_p
# Use glade for plugins that still uses it
import gtk
import gtk.glade
gtk.glade.bindtextdomain(domain, translations_path)
gtk.glade.textdomain(domain)
except Exception as ex:
log.error("Unable to initialize glade translation!")
log.exception(ex)
if setup_gettext:
try:
if hasattr(locale, "bindtextdomain"):
locale.bindtextdomain(domain, translations_path)
if hasattr(locale, "textdomain"):
locale.textdomain(domain)
gettext.bindtextdomain(domain, translations_path)
gettext.bind_textdomain_codeset(domain, 'UTF-8')
gettext.textdomain(domain)
gettext.install(domain, translations_path, unicode=True)
except Exception as ex:
log.error("Unable to initialize gettext/locale!")
log.exception(ex)
set_dummy_trans()
deluge.common.translate_size_units()

View File

@ -36,25 +36,48 @@ Deluge.preferences.Interface = Ext.extend(Ext.form.FormPanel, {
}); });
om.bind('show_session_speed', fieldset.add({ om.bind('show_session_speed', fieldset.add({
name: 'show_session_speed', name: 'show_session_speed',
height: 22, height: 17,
fieldLabel: '', fieldLabel: '',
labelSeparator: '', labelSeparator: '',
boxLabel: _('Show session speed in titlebar') boxLabel: _('Show session speed in titlebar')
})); }));
om.bind('sidebar_show_zero', fieldset.add({ om.bind('sidebar_show_zero', fieldset.add({
name: 'sidebar_show_zero', name: 'sidebar_show_zero',
height: 22, height: 17,
fieldLabel: '', fieldLabel: '',
labelSeparator: '', labelSeparator: '',
boxLabel: _('Show filters with zero torrents') boxLabel: _('Show filters with zero torrents')
})); }));
om.bind('sidebar_multiple_filters', fieldset.add({ om.bind('sidebar_multiple_filters', fieldset.add({
name: 'sidebar_multiple_filters', name: 'sidebar_multiple_filters',
height: 22, height: 17,
fieldLabel: '', fieldLabel: '',
labelSeparator: '', labelSeparator: '',
boxLabel: _('Allow the use of multiple filters at once') boxLabel: _('Allow the use of multiple filters at once')
})); }));
var languagePanel = this.add({
xtype: 'fieldset',
border: false,
title: _('Language'),
style: 'margin-bottom: 0px; padding-bottom: 5px; padding-top: 8px',
autoHeight: true,
labelWidth: 1,
defaultType: 'checkbox'
});
this.language = om.bind('language', languagePanel.add({
xtype: 'combo',
labelSeparator: '',
name: 'language',
mode: 'local',
width: 200,
store: new Ext.data.ArrayStore({
fields: ['id', 'text']
}),
editable: false,
triggerAction: 'all',
valueField: 'id',
displayField: 'text'
}));
fieldset = this.add({ fieldset = this.add({
xtype: 'fieldset', xtype: 'fieldset',
@ -73,16 +96,19 @@ Deluge.preferences.Interface = Ext.extend(Ext.form.FormPanel, {
this.oldPassword = fieldset.add({ this.oldPassword = fieldset.add({
name: 'old_password', name: 'old_password',
fieldLabel: _('Old Password:'), fieldLabel: _('Old Password:'),
height: 20,
labelSeparator: '' labelSeparator: ''
}); });
this.newPassword = fieldset.add({ this.newPassword = fieldset.add({
name: 'new_password', name: 'new_password',
fieldLabel: _('New Password:'), fieldLabel: _('New Password:'),
height: 20,
labelSeparator: '' labelSeparator: ''
}); });
this.confirmPassword = fieldset.add({ this.confirmPassword = fieldset.add({
name: 'confirm_password', name: 'confirm_password',
fieldLabel: _('Confirm Password:'), fieldLabel: _('Confirm Password:'),
height: 20,
labelSeparator: '' labelSeparator: ''
}); });
@ -137,7 +163,7 @@ Deluge.preferences.Interface = Ext.extend(Ext.form.FormPanel, {
name: 'https', name: 'https',
hideLabel: true, hideLabel: true,
width: 280, width: 280,
height: 22, height: 17,
boxLabel: _('Use SSL (paths relative to Deluge config folder)') boxLabel: _('Use SSL (paths relative to Deluge config folder)')
})); }));
this.httpsField.on('check', this.onSSLCheck, this); this.httpsField.on('check', this.onSSLCheck, this);
@ -177,6 +203,12 @@ Deluge.preferences.Interface = Ext.extend(Ext.form.FormPanel, {
this.optionsManager.set(config); this.optionsManager.set(config);
}, },
onGotLanguages: function(info, obj, response, request) {
info.unshift(['', _('System Default')])
this.language.store.loadData(info);
this.language.setValue(this.optionsManager.get('language'));
},
onPasswordChange: function() { onPasswordChange: function() {
var newPassword = this.newPassword.getValue(); var newPassword = this.newPassword.getValue();
if (newPassword != this.confirmPassword.getValue()) { if (newPassword != this.confirmPassword.getValue()) {
@ -230,7 +262,11 @@ Deluge.preferences.Interface = Ext.extend(Ext.form.FormPanel, {
deluge.client.web.get_config({ deluge.client.web.get_config({
success: this.onGotConfig, success: this.onGotConfig,
scope: this scope: this
}) });
deluge.client.webutils.get_languages({
success: this.onGotLanguages,
scope: this,
});
}, },
onSSLCheck: function(e, checked) { onSSLCheck: function(e, checked) {

View File

@ -1,5 +1,6 @@
GetText={maps:{}, add:function(string,translation) {this.maps[string]=translation}, get:function(string) {if (this.maps[string]) {string=this.maps[string]} return string}} GetText={maps:{}, add:function(string,translation) {this.maps[string]=translation}, get:function(string) {if (this.maps[string]) {string=this.maps[string]} return string}}
function _(string) {return GetText.get(string)} GetText.add('10 KiB/s','${escape(_("10 KiB/s"))}') function _(string) {return GetText.get(string)}
GetText.add('10 KiB/s','${escape(_("10 KiB/s"))}')
GetText.add('30 KiB/s','${escape(_("30 KiB/s"))}') GetText.add('30 KiB/s','${escape(_("30 KiB/s"))}')
GetText.add('300 KiB/s','${escape(_("300 KiB/s"))}') GetText.add('300 KiB/s','${escape(_("300 KiB/s"))}')
GetText.add('5 KiB/s','${escape(_("5 KiB/s"))}') GetText.add('5 KiB/s','${escape(_("5 KiB/s"))}')
@ -130,6 +131,7 @@ GetText.add('Invalid Password','${escape(_("Invalid Password"))}')
GetText.add('KiB/s','${escape(_("KiB/s"))}') GetText.add('KiB/s','${escape(_("KiB/s"))}')
GetText.add('LSD','${escape(_("LSD"))}') GetText.add('LSD','${escape(_("LSD"))}')
GetText.add('Labels','${escape(_("Labels"))}') GetText.add('Labels','${escape(_("Labels"))}')
GetText.add('Language:','${escape(_("Language:"))}')
GetText.add('Level:','${escape(_("Level:"))}') GetText.add('Level:','${escape(_("Level:"))}')
GetText.add('Loading','${escape(_("Loading"))}') GetText.add('Loading','${escape(_("Loading"))}')
GetText.add('Login','${escape(_("Login"))}') GetText.add('Login','${escape(_("Login"))}')

View File

@ -27,6 +27,7 @@ from deluge.ui import common as uicommon
from deluge.ui.client import Client, client from deluge.ui.client import Client, client
from deluge.ui.coreconfig import CoreConfig from deluge.ui.coreconfig import CoreConfig
from deluge.ui.sessionproxy import SessionProxy from deluge.ui.sessionproxy import SessionProxy
from deluge.ui.util import lang
from deluge.ui.web.common import _, compress from deluge.ui.web.common import _, compress
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -957,3 +958,21 @@ class WebApi(JSONComponent):
Retrieve the pending events for the session. Retrieve the pending events for the session.
""" """
return self.event_queue.get_events(__request__.session_id) return self.event_queue.get_events(__request__.session_id)
class WebUtils(JSONComponent):
"""
"""
def __init__(self):
super(WebUtils, self).__init__("WebUtils")
@export
def get_languages(self):
"""
Get the available translated languages
Returns:
list: of tuples [(lang-id, language-name), ...]
"""
return lang.get_languages()

View File

@ -23,9 +23,10 @@ from twisted.web import http, resource, server, static
from deluge import common, component, configmanager from deluge import common, component, configmanager
from deluge.core.rpcserver import check_ssl_keys from deluge.core.rpcserver import check_ssl_keys
from deluge.ui.tracker_icons import TrackerIcons from deluge.ui.tracker_icons import TrackerIcons
from deluge.ui.util import lang
from deluge.ui.web.auth import Auth from deluge.ui.web.auth import Auth
from deluge.ui.web.common import Template, compress from deluge.ui.web.common import Template, compress
from deluge.ui.web.json_api import JSON, WebApi from deluge.ui.web.json_api import JSON, WebApi, WebUtils
from deluge.ui.web.pluginmanager import PluginManager from deluge.ui.web.pluginmanager import PluginManager
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -48,6 +49,7 @@ CONFIG_DEFAULTS = {
"show_sidebar": True, "show_sidebar": True,
"theme": "gray", "theme": "gray",
"first_login": True, "first_login": True,
"language": "",
# Server Settings # Server Settings
"base": "/", "base": "/",
@ -533,6 +535,8 @@ class DelugeWeb(component.Component):
def __init__(self, options=None): def __init__(self, options=None):
super(DelugeWeb, self).__init__("DelugeWeb") super(DelugeWeb, self).__init__("DelugeWeb")
self.config = configmanager.ConfigManager("web.conf", CONFIG_DEFAULTS) self.config = configmanager.ConfigManager("web.conf", CONFIG_DEFAULTS)
self.config.run_converter((0, 1), 2, self._migrate_config_1_to_2)
self.config.register_set_function("language", self._on_language_changed)
self.socket = None self.socket = None
self.top_level = TopLevel() self.top_level = TopLevel()
@ -556,13 +560,21 @@ class DelugeWeb(component.Component):
# Strip away slashes and serve on the base path as well as root path # Strip away slashes and serve on the base path as well as root path
self.top_level.putChild(self.base.strip('/'), self.top_level) self.top_level.putChild(self.base.strip('/'), self.top_level)
lang.setup_translations(setup_gettext=True, setup_pygtk=False)
self.site = server.Site(self.top_level) self.site = server.Site(self.top_level)
self.web_api = WebApi() self.web_api = WebApi()
self.web_utils = WebUtils()
self.auth = Auth(self.config) self.auth = Auth(self.config)
self.standalone = True self.standalone = True
# Initalize the plugins # Initalize the plugins
self.plugins = PluginManager() self.plugins = PluginManager()
def _on_language_changed(self, key, value):
log.debug("Setting UI language '%s'", value)
lang.set_language(value)
def install_signal_handlers(self): def install_signal_handlers(self):
# Since twisted assigns itself all the signals may as well make # Since twisted assigns itself all the signals may as well make
# use of it. # use of it.
@ -648,6 +660,10 @@ class DelugeWeb(component.Component):
if self.standalone and reactor.running: if self.standalone and reactor.running:
reactor.stop() reactor.stop()
def _migrate_config_1_to_2(self, config):
config["language"] = CONFIG_DEFAULTS["language"]
return config
if __name__ == "__builtin__": if __name__ == "__builtin__":
deluge_web = DelugeWeb() deluge_web = DelugeWeb()