From d9196154755db9ff04f600ce4f22c050996cea5a Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Wed, 18 Apr 2012 03:06:38 +0900 Subject: [PATCH] refactor language handling Because Qt translations need to be initialized before any widgets are created, and because the Qt language needs to match the gettext language in order for translated shortcuts to work, per-profile language settings aren't possible. So instead of storing the language in the profile, we use pm.meta['defaultLang'] for all profiles and initialize language handling in __init__.py The language selection in the preferences has been removed, because in a school setting a student fiddling with the language could potentially cause other students to be unable to navigate the UI. Instead, Anki will accept -l/--lang passed on the command line to override the original language chosen at first program startup. --- aqt/__init__.py | 53 ++++++++++++++++++++++++++++++++++------- aqt/main.py | 49 ------------------------------------- aqt/preferences.py | 31 ------------------------ aqt/profiles.py | 2 -- designer/preferences.ui | 26 ++------------------ 5 files changed, 46 insertions(+), 115 deletions(-) diff --git a/aqt/__init__.py b/aqt/__init__.py index 3c02be939..8733c9236 100644 --- a/aqt/__init__.py +++ b/aqt/__init__.py @@ -1,8 +1,10 @@ # Copyright: Damien Elmes # License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html -import os, sys +import os, sys, __builtin__ from aqt.qt import * +import locale, gettext +import anki.lang appVersion="2.0-beta3" appWebsite="http://ankisrs.net/" @@ -49,6 +51,44 @@ class DialogManager(object): dialogs = DialogManager() +# Language handling +########################################################################## +# Qt requires its translator to be installed before any GUI widgets are +# loaded, and we need the Qt language to match the gettext language or +# translated shortcuts will not work. + +_gtrans = None +_qtrans = None + +def langDir(): + dir = os.path.join(moduleDir, "aqt", "locale") + if not os.path.exists(dir): + dir = os.path.join(os.path.dirname(sys.argv[0]), "locale") + return dir + +def setupLang(pm, app, force=None): + global _gtrans, _qtrans + try: + locale.setlocale(locale.LC_ALL, '') + except: + pass + lang = force or pm.meta["defaultLang"] + dir = langDir() + # gettext + _gtrans = gettext.translation( + 'ankiqt', dir, languages=[lang], fallback=True) + __builtin__.__dict__['_'] = _gtrans.ugettext + __builtin__.__dict__['ngettext'] = _gtrans.ungettext + anki.lang.setLang(lang, local=False) + if lang in ("he","ar","fa"): + app.setLayoutDirection(Qt.RightToLeft) + else: + app.setLayoutDirection(Qt.LeftToRight) + # qt + _qtrans = QTranslator() + if _qtrans.load("qt_" + lang, dir): + app.installTranslator(_qtrans) + # App initialisation ########################################################################## @@ -80,20 +120,15 @@ def run(): parser.usage = "%prog [OPTIONS]" parser.add_option("-b", "--base", help="Path to base folder") parser.add_option("-p", "--profile", help="Profile name to load") + parser.add_option("-l", "--lang", help="Interface language (en, de, etc)") (opts, args) = parser.parse_args(sys.argv[1:]) # profile manager from aqt.profiles import ProfileManager pm = ProfileManager(opts.base, opts.profile) - # qt translations - qtTranslator = QTranslator() - languageDir = os.path.join(moduleDir, "aqt", "locale") - if not os.path.exists(languageDir): - languageDir = os.path.join( - os.path.dirname(sys.argv[0]), "locale") - if qtTranslator.load("qt_" + pm.meta['defaultLang'], languageDir): - app.installTranslator(qtTranslator) + # i18n + setupLang(pm, app, opts.lang) import aqt.main mw = aqt.main.AnkiQt(app, pm) diff --git a/aqt/main.py b/aqt/main.py index c5129127d..ee793cadb 100755 --- a/aqt/main.py +++ b/aqt/main.py @@ -21,20 +21,12 @@ from aqt.utils import saveGeom, restoreGeom, showInfo, showWarning, \ askUserDialog, applyStyles, getText, showText, showCritical, getFile, \ tooltip, openHelp, openLink -## fixme: open plugin folder broken on win32? - -## models remembering the previous group - class AnkiQt(QMainWindow): def __init__(self, app, profileManager): QMainWindow.__init__(self) aqt.mw = self self.app = app self.pm = profileManager - # use the global language for early init; once a profile or the - # profile manager is loaded we can switch to a user's preferred - # language - self.setupLang(force=self.pm.meta['defaultLang']) # running 2.0 for the first time? if self.pm.meta['firstRun']: # load the new deck user profile @@ -100,7 +92,6 @@ class AnkiQt(QMainWindow): self.loadProfile() def showProfileManager(self): - self.setupLang(force=self.pm.meta['defaultLang']) d = self.profileDiag = QDialog() f = self.profileForm = aqt.forms.profiles.Ui_Dialog() f.setupUi(d) @@ -191,7 +182,6 @@ Are you sure?"""): self.refreshProfilesList() def loadProfile(self): - self.setupLang() # show main window if self.pm.profile['mainWindowState']: restoreGeom(self, "mainWindow") @@ -755,45 +745,6 @@ upload, overwriting any changes either here or on AnkiWeb. Proceed?""")): else: self.moveToState("overview") - # Language handling - ########################################################################## - - def setupLang(self, force=None): - "Set the user interface language for the current profile." - import locale, gettext - import anki.lang - try: - locale.setlocale(locale.LC_ALL, '') - except: - pass - lang = force if force else self.pm.profile["lang"] - languageDir=os.path.join(aqt.moduleDir, "aqt", "locale") - if not os.path.exists(languageDir): - languageDir = os.path.join( - os.path.dirname(sys.argv[0]), "locale") - self.languageTrans = gettext.translation('ankiqt', languageDir, - languages=[lang], - fallback=True) - self.installTranslation() - if getattr(self, 'form', None): - self.form.retranslateUi(self) - anki.lang.setLang(lang, local=False) - if lang in ("he","ar","fa"): - self.app.setLayoutDirection(Qt.RightToLeft) - else: - self.app.setLayoutDirection(Qt.LeftToRight) - - def getTranslation(self, text): - return self.languageTrans.ugettext(text) - - def getTranslation2(self, text1, text2, n): - return self.languageTrans.ungettext(text1, text2, n) - - def installTranslation(self): - import __builtin__ - __builtin__.__dict__['_'] = self.getTranslation - __builtin__.__dict__['ngettext'] = self.getTranslation2 - # Menu, title bar & status ########################################################################## diff --git a/aqt/preferences.py b/aqt/preferences.py index d73391448..79ad27deb 100644 --- a/aqt/preferences.py +++ b/aqt/preferences.py @@ -4,7 +4,6 @@ import datetime, time, os from aqt.qt import * -from anki.lang import langs from aqt.utils import openFolder, showWarning, getText, openHelp import aqt @@ -19,7 +18,6 @@ class Preferences(QDialog): self.connect(self.form.buttonBox, SIGNAL("helpRequested()"), lambda: openHelp("profileprefs")) self.setupCollection() - self.setupLang() self.setupNetwork() self.setupBackup() self.setupOptions() @@ -69,35 +67,6 @@ class Preferences(QDialog): d.crt = int(time.mktime(date.timetuple())) d.setMod() - # Language handling - ###################################################################### - - def setupLang(self): - # interface lang - for (lang, code) in langs: - self.form.interfaceLang.addItem(lang) - self.form.interfaceLang.setCurrentIndex( - self.codeToIndex(self.prof['lang'])) - self.connect(self.form.interfaceLang, - SIGNAL("currentIndexChanged(QString)"), - self.interfaceLangChanged) - - def codeToIndex(self, code): - n = 0 - for (lang, type) in langs: - if code == type: - return n - n += 1 - # default to english - return self.codeToIndex("en") - - def interfaceLangChanged(self): - self.prof['lang'] = ( - langs[self.form.interfaceLang.currentIndex()])[1] - self.mw.setupLang() - self.form.retranslateUi(self) - - # Network ###################################################################### diff --git a/aqt/profiles.py b/aqt/profiles.py index a25185a71..eb5e25d30 100644 --- a/aqt/profiles.py +++ b/aqt/profiles.py @@ -33,7 +33,6 @@ profileConf = dict( mainWindowState=None, numBackups=30, lastOptimize=intTime(), - lang="en", # editing fullSearch=False, @@ -142,7 +141,6 @@ computer.""") def create(self, name): prof = profileConf.copy() - prof['lang'] = self.meta['defaultLang'] self.db.execute("insert into profiles values (?, ?)", name, cPickle.dumps(prof)) self.db.commit() diff --git a/designer/preferences.ui b/designer/preferences.ui index 5ad547833..4f8274a55 100644 --- a/designer/preferences.ui +++ b/designer/preferences.ui @@ -6,8 +6,8 @@ 0 0 - 439 - 420 + 441 + 426 @@ -30,27 +30,6 @@ 12 - - - - - - Language: - - - - - - - - 300 - 0 - - - - - - @@ -483,7 +462,6 @@ - interfaceLang showEstimates showProgress stripHTML