mirror of
https://github.com/codex-storage/deluge.git
synced 2025-03-02 12:00:44 +00:00
[#1959] [WebUI] Allow user selectable GUI language
This commit is contained in:
parent
74f2f45fc0
commit
857e2fd46e
@ -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():
|
||||||
|
@ -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()
|
||||||
|
@ -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):
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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):
|
||||||
|
@ -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
|
||||||
|
0
deluge/ui/util/__init__.py
Normal file
0
deluge/ui/util/__init__.py
Normal file
119
deluge/ui/util/lang.py
Normal file
119
deluge/ui/util/lang.py
Normal 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()
|
@ -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) {
|
||||||
|
@ -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"))}')
|
||||||
|
@ -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()
|
||||||
|
@ -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()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user