Merge pull request #835 from abdnh/init-lang

Set up default language before loading profile
This commit is contained in:
Damien Elmes 2020-11-22 16:25:44 +10:00 committed by GitHub
commit 0c08ff5317
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 82 additions and 50 deletions

View File

@ -8,3 +8,8 @@ profiles-profile-corrupt = Profile Corrupt
profiles-profiles = Profiles
profiles-quit = Quit
profiles-user-1 = User 1
profiles-confirm-lang-choice = Are you sure you wish to display Anki's interface in { $lang }?
profiles-could-not-create-data-folder = Anki could not create its data folder. Please see the File Locations section of the manual, and ensure that location is not read-only.
profiles-prefs-corrupt-title = Preferences Corrupt
profiles-prefs-file-is-corrupt = Anki's prefs21.db file was corrupt and has been recreated. If you were using multiple profiles, please add them back using the same names to recover your cards.
profiles-profile-does-not-exist = Requested profile does not exist.

View File

@ -61,6 +61,12 @@ qt-misc-would-you-like-to-download-it = Would you like to download it now?
qt-misc-your-collection-file-appears-to-be = Your collection file appears to be corrupt. This can happen when the file is copied or moved while Anki is open, or when the collection is stored on a network or cloud drive. If problems persist after restarting your computer, please open an automatic backup from the profile screen.
qt-misc-your-computers-storage-may-be-full = Your computer's storage may be full. Please delete some unneeded files, then try again.
qt-misc-your-firewall-or-antivirus-program-is = Your firewall or antivirus program is preventing Anki from creating a connection to itself. Please add an exception for Anki.
qt-misc-error = Error
qt-misc-no-temp-folder = No usable temporary folder found. Make sure C:\\temp exists or TEMP in your environment points to a valid, writable folder.
qt-misc-incompatible-video-driver = Your video driver is incompatible. Please start Anki again, and Anki will switch to a slower, more compatible mode.
qt-misc-error-loading-graphics-driver = Error loading '{ $mode }' graphics driver. Please start Anki again to try next driver. { $context }
qt-misc-anki-is-running = Anki Already Running
qt-misc-if-instance-is-not-responding = If the existing instance of Anki is not responding, please close it using your task manager, or restart your computer.
qt-misc-second =
{ $count ->
[one] { $count } second

View File

@ -3,8 +3,9 @@
from __future__ import annotations
import locale
import re
from typing import Optional
from typing import Optional, Tuple
import anki
@ -171,6 +172,36 @@ def set_lang(lang: str, locale_dir: str) -> None:
locale_folder = locale_dir
def get_def_lang(lang: Optional[str] = None) -> Tuple[int, str]:
"""Return lang converted to name used on disk and its index, defaulting to system language
or English if not available."""
try:
(sys_lang, enc) = locale.getdefaultlocale()
except:
# fails on osx
sys_lang = "en_US"
user_lang = lang
if user_lang in compatMap:
user_lang = compatMap[user_lang]
idx = None
lang = None
en = None
for l in (user_lang, sys_lang):
for c, (name, code) in enumerate(langs):
if code == "en_US":
en = c
if code == l:
idx = c
lang = l
if idx is not None:
break
# if the specified language and the system language aren't available, revert to english
if idx is None:
idx = en
lang = "en_US"
return (idx, lang)
def is_rtl(lang: str) -> bool:
return lang in ("he", "ar", "fa")

View File

@ -17,7 +17,7 @@ from anki.consts import HELP_SITE
from anki.rsbackend import RustBackend
from anki.utils import checksum, isLin, isMac
from aqt.qt import *
from aqt.utils import locale_dir
from aqt.utils import TR, locale_dir, tr
# we want to be able to print unicode debug info to console without
# fear of a traceback on systems with the console set to ASCII
@ -175,7 +175,10 @@ _qtrans: Optional[QTranslator] = None
def setupLangAndBackend(
pm: ProfileManager, app: QApplication, force: Optional[str] = None
pm: ProfileManager,
app: QApplication,
force: Optional[str] = None,
firstTime: bool = False,
) -> RustBackend:
global _qtrans
try:
@ -198,12 +201,16 @@ def setupLangAndBackend(
builtins.__dict__["ngettext"] = fn_ngettext
# get lang and normalize into ja/zh-CN form
lang = force or pm.meta["defaultLang"]
if firstTime:
lang = pm.meta["defaultLang"]
else:
lang = force or pm.meta["defaultLang"]
lang = anki.lang.lang_to_disk_lang(lang)
# set active language
ldir = locale_dir()
anki.lang.set_lang(lang, ldir)
if not firstTime:
# set active language
anki.lang.set_lang(lang, ldir)
# switch direction for RTL languages
if anki.lang.is_rtl(lang):
@ -269,8 +276,8 @@ class AnkiApp(QApplication):
# existing instance running but hung
QMessageBox.warning(
None,
"Anki Already Running",
"If the existing instance of Anki is not responding, please close it using your task manager, or restart your computer.",
tr(TR.QT_MISC_ANKI_IS_RUNNING),
tr(TR.QT_MISC_IF_INSTANCE_IS_NOT_RESPONDING),
)
sys.exit(1)
@ -356,8 +363,10 @@ def setupGL(pm):
if "Failed to create OpenGL context" in msg:
QMessageBox.critical(
None,
"Error",
f"Error loading '{mode}' graphics driver. Please start Anki again to try next driver. {context}",
tr(TR.QT_MISC_ERROR),
tr(
TR.QT_MISC_ERROR_LOADING_GRAPHICS_DRIVER, mode=mode, context=context
),
)
pm.nextGlMode()
return
@ -427,6 +436,10 @@ def _run(argv=None, exec=True):
profiler = cProfile.Profile()
profiler.enable()
# default to specified/system language before getting user's preference so that we can localize some more strings
lang = anki.lang.get_def_lang(opts.lang)
anki.lang.set_lang(lang[1], locale_dir())
# profile manager
pm = None
try:
@ -475,10 +488,8 @@ def _run(argv=None, exec=True):
if not pm:
QMessageBox.critical(
None,
"Error",
"""\
Anki could not create its data folder. Please see the File Locations \
section of the manual, and ensure that location is not read-only.""",
tr(TR.QT_MISC_ERROR),
tr(TR.PROFILES_COULD_NOT_CREATE_DATA_FOLDER),
)
return
@ -517,29 +528,26 @@ section of the manual, and ensure that location is not read-only.""",
except:
QMessageBox.critical(
None,
"Error",
"""\
No usable temporary folder found. Make sure C:\\temp exists or TEMP in your \
environment points to a valid, writable folder.""",
tr(TR.QT_MISC_ERROR),
tr(TR.QT_MISC_NO_TEMP_FOLDER),
)
return
if pmLoadResult.firstTime:
pm.setDefaultLang()
pm.setDefaultLang(lang[0])
if pmLoadResult.loadError:
QMessageBox.warning(
None,
"Preferences Corrupt",
"""Anki's prefs21.db file was corrupt and has been recreated. If you were using multiple \
profiles, please add them back using the same names to recover your cards.""",
tr(TR.PROFILES_PREFS_CORRUPT_TITLE),
tr(TR.PROFILES_PREFS_FILE_IS_CORRUPT),
)
if opts.profile:
pm.openProfile(opts.profile)
# i18n & backend
backend = setupLangAndBackend(pm, app, opts.lang)
backend = setupLangAndBackend(pm, app, opts.lang, pmLoadResult.firstTime)
if isLin and pm.glMode() == "auto":
from aqt.utils import gfxDriverIsBroken
@ -548,8 +556,8 @@ environment points to a valid, writable folder.""",
pm.nextGlMode()
QMessageBox.critical(
None,
"Error",
"Your video driver is incompatible. Please start Anki again, and Anki will switch to a slower, more compatible mode.",
tr(TR.QT_MISC_ERROR),
tr(TR.QT_MISC_INCOMPATIBLE_VIDEO_DRIVER),
)
sys.exit(1)

View File

@ -97,7 +97,9 @@ class ProfileManager:
def openProfile(self, profile) -> None:
if profile:
if profile not in self.profiles():
QMessageBox.critical(None, "Error", "Requested profile does not exist.")
QMessageBox.critical(
None, tr(TR.QT_MISC_ERROR), tr(TR.PROFILES_PROFILE_DOES_NOT_EXIST)
)
sys.exit(1)
try:
self.load(profile)
@ -482,7 +484,7 @@ create table if not exists profiles
######################################################################
# On first run, allow the user to choose the default language
def setDefaultLang(self) -> None:
def setDefaultLang(self, idx: int) -> None:
# create dialog
class NoCloseDiag(QDialog):
def reject(self):
@ -490,28 +492,9 @@ create table if not exists profiles
d = self.langDiag = NoCloseDiag()
f = self.langForm = aqt.forms.setlang.Ui_Dialog()
f.setupUi(d)
qconnect(d.accepted, self._onLangSelected)
qconnect(d.rejected, lambda: True)
# default to the system language
try:
(lang, enc) = locale.getdefaultlocale()
except:
# fails on osx
lang = "en_US"
# find index
idx = None
en = None
for c, (name, code) in enumerate(anki.lang.langs):
if code == "en_US":
en = c
if code == lang:
idx = c
# if the system language isn't available, revert to english
if idx is None:
idx = en
lang = "en_US"
anki.lang.set_lang(lang, locale_dir())
f.setupUi(d)
# update list
f.lang.addItems([x[0] for x in anki.lang.langs])
f.lang.setCurrentRow(idx)
@ -522,12 +505,11 @@ create table if not exists profiles
obj = anki.lang.langs[f.lang.currentRow()]
code = obj[1]
name = obj[0]
en = "Are you sure you wish to display Anki's interface in %s?"
r = QMessageBox.question(
None, "Anki", en % name, QMessageBox.Yes | QMessageBox.No, QMessageBox.No # type: ignore
None, "Anki", tr(TR.PROFILES_CONFIRM_LANG_CHOICE, lang=name), QMessageBox.Yes | QMessageBox.No, QMessageBox.No # type: ignore
)
if r != QMessageBox.Yes:
return self.setDefaultLang()
return self.setDefaultLang(f.lang.currentRow())
self.setLang(code)
def setLang(self, code) -> None: