mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 14:02:21 -04:00
update multi-line _() references
This commit is contained in:
parent
b49805fef5
commit
ba336d5de3
20 changed files with 57 additions and 315 deletions
|
@ -93,14 +93,8 @@ def show(mw):
|
|||
# WebView contents
|
||||
######################################################################
|
||||
abouttext = "<center><img src='/_anki/imgs/anki-logo-thin.png'></center>"
|
||||
abouttext += "<p>" + _(
|
||||
"Anki is a friendly, intelligent spaced learning \
|
||||
system. It's free and open source."
|
||||
)
|
||||
abouttext += "<p>" + _(
|
||||
"Anki is licensed under the AGPL3 license. Please see "
|
||||
"the license file in the source distribution for more information."
|
||||
)
|
||||
abouttext += "<p>" + tr(TR.ABOUT_ANKI_IS_A_FRIENDLY_INTELLIGENT_SPACED)
|
||||
abouttext += "<p>" + tr(TR.ABOUT_ANKI_IS_LICENSED_UNDER_THE_AGPL3)
|
||||
abouttext += "<p>" + tr(TR.ABOUT_VERSION, val=versionWithBuild()) + "<br>"
|
||||
abouttext += ("Python %s Qt %s PyQt %s<br>") % (
|
||||
platform.python_version(),
|
||||
|
@ -209,22 +203,11 @@ system. It's free and open source."
|
|||
)
|
||||
)
|
||||
|
||||
abouttext += (
|
||||
"<p>"
|
||||
+ _(
|
||||
"Written by Damien Elmes, with patches, translation,\
|
||||
testing and design from:<p>%(cont)s"
|
||||
)
|
||||
% {"cont": ", ".join(allusers)}
|
||||
)
|
||||
abouttext += "<p>" + _(
|
||||
"If you have contributed and are not on this list, \
|
||||
please get in touch."
|
||||
)
|
||||
abouttext += "<p>" + _(
|
||||
"A big thanks to all the people who have provided \
|
||||
suggestions, bug reports and donations."
|
||||
)
|
||||
abouttext += "<p>" + tr(TR.ABOUT_WRITTEN_BY_DAMIEN_ELMES_WITH_PATCHES) % {
|
||||
"cont": ", ".join(allusers)
|
||||
}
|
||||
abouttext += "<p>" + tr(TR.ABOUT_IF_YOU_HAVE_CONTRIBUTED_AND_ARE)
|
||||
abouttext += "<p>" + tr(TR.ABOUT_A_BIG_THANKS_TO_ALL_THE)
|
||||
abt.label.setMinimumWidth(800)
|
||||
abt.label.setMinimumHeight(600)
|
||||
dialog.show()
|
||||
|
|
|
@ -175,12 +175,7 @@ class AddCards(QDialog):
|
|||
return None
|
||||
if note.model()["type"] == MODEL_CLOZE:
|
||||
if not note.cloze_numbers_in_fields():
|
||||
if not askUser(
|
||||
_(
|
||||
"You have a cloze deletion note type "
|
||||
"but have not made any cloze deletions. Proceed?"
|
||||
)
|
||||
):
|
||||
if not askUser(tr(TR.ADDING_YOU_HAVE_A_CLOZE_DELETION_NOTE)):
|
||||
return None
|
||||
self.mw.col.add_note(note, self.deckChooser.selectedId())
|
||||
self.mw.col.clearUndo()
|
||||
|
|
|
@ -836,12 +836,7 @@ class AddonsDialog(QDialog):
|
|||
if not selected:
|
||||
return
|
||||
if not askUser(
|
||||
ngettext(
|
||||
"Delete the %(num)d selected add-on?",
|
||||
"Delete the %(num)d selected add-ons?",
|
||||
len(selected),
|
||||
)
|
||||
% dict(num=len(selected))
|
||||
tr(TR.ADDONS_DELETE_THE_NUMD_SELECTED_ADDON, count=len(selected))
|
||||
):
|
||||
return
|
||||
for dir in selected:
|
||||
|
|
|
@ -17,7 +17,6 @@ import aqt.forms
|
|||
from anki.cards import Card
|
||||
from anki.collection import Collection
|
||||
from anki.consts import *
|
||||
from anki.lang import _, ngettext
|
||||
from anki.models import NoteType
|
||||
from anki.notes import Note
|
||||
from anki.rsbackend import TR, DeckTreeNode, InvalidInput
|
||||
|
@ -821,16 +820,10 @@ class Browser(QMainWindow):
|
|||
def updateTitle(self):
|
||||
selected = len(self.form.tableView.selectionModel().selectedRows())
|
||||
cur = len(self.model.cards)
|
||||
print("fixme: browser updateTitle()")
|
||||
self.setWindowTitle(
|
||||
ngettext(
|
||||
"Browse (%(cur)d card shown; %(sel)s)",
|
||||
"Browse (%(cur)d cards shown; %(sel)s)",
|
||||
cur,
|
||||
)
|
||||
% {
|
||||
"cur": cur,
|
||||
"sel": ngettext("%d selected", "%d selected", selected) % selected,
|
||||
}
|
||||
"Browse (%(cur)d cards shown; %(sel)s)"
|
||||
% {"cur": cur, "sel": self.col.tr(TR.BROWSING_SELECTED, count=selected)}
|
||||
)
|
||||
return selected
|
||||
|
||||
|
@ -2266,14 +2259,7 @@ class ChangeModel(QDialog):
|
|||
fmap = self.getFieldMap()
|
||||
cmap = self.getTemplateMap()
|
||||
if any(True for c in list(cmap.values()) if c is None):
|
||||
if not askUser(
|
||||
_(
|
||||
"""\
|
||||
Any cards mapped to nothing will be deleted. \
|
||||
If a note has no remaining cards, it will be lost. \
|
||||
Are you sure you want to continue?"""
|
||||
)
|
||||
):
|
||||
if not askUser(tr(TR.BROWSING_ANY_CARDS_MAPPED_TO_NOTHING_WILL)):
|
||||
return
|
||||
self.browser.mw.checkpoint(tr(TR.BROWSING_CHANGE_NOTE_TYPE))
|
||||
b = self.browser
|
||||
|
|
|
@ -9,7 +9,6 @@ from typing import Any, Dict, List, Optional
|
|||
import aqt
|
||||
from anki.cards import Card
|
||||
from anki.consts import *
|
||||
from anki.lang import _, ngettext
|
||||
from anki.notes import Note
|
||||
from anki.rsbackend import TemplateError
|
||||
from anki.template import TemplateRenderContext
|
||||
|
@ -656,13 +655,7 @@ class CardLayout(QDialog):
|
|||
def _flipQA(self, src, dst):
|
||||
m = re.match("(?s)(.+)<hr id=answer>(.+)", src["afmt"])
|
||||
if not m:
|
||||
showInfo(
|
||||
_(
|
||||
"""\
|
||||
Anki couldn't find the line between the question and answer. Please \
|
||||
adjust the template manually to switch the question and answer."""
|
||||
)
|
||||
)
|
||||
showInfo(tr(TR.CARD_TEMPLATES_ANKI_COULDNT_FIND_THE_LINE_BETWEEN))
|
||||
return
|
||||
self.change_tracker.mark_basic()
|
||||
dst["afmt"] = "{{FrontSide}}\n\n<hr id=answer>\n\n%s" % src["qfmt"]
|
||||
|
@ -736,10 +729,7 @@ adjust the template manually to switch the question and answer."""
|
|||
d.setMinimumWidth(400)
|
||||
l = QVBoxLayout()
|
||||
lab = QLabel(
|
||||
_(
|
||||
"""\
|
||||
Enter deck to place new %s cards in, or leave blank:"""
|
||||
)
|
||||
tr(TR.CARD_TEMPLATES_ENTER_DECK_TO_PLACE_NEW, val="%s")
|
||||
% self.current_template()["name"]
|
||||
)
|
||||
lab.setWordWrap(True)
|
||||
|
|
|
@ -8,7 +8,6 @@ from dataclasses import dataclass
|
|||
|
||||
import aqt
|
||||
from anki.errors import DeckRenameError
|
||||
from anki.lang import _, ngettext
|
||||
from anki.rsbackend import TR, DeckTreeNode
|
||||
from anki.utils import ids2str
|
||||
from aqt import AnkiQt, gui_hooks
|
||||
|
|
|
@ -8,7 +8,6 @@ from PyQt5.QtWidgets import QLineEdit
|
|||
|
||||
import aqt
|
||||
from anki.consts import NEW_CARDS_RANDOM
|
||||
from anki.lang import _, ngettext
|
||||
from aqt import gui_hooks
|
||||
from aqt.qt import *
|
||||
from aqt.utils import (
|
||||
|
@ -110,10 +109,7 @@ class DeckConf(QDialog):
|
|||
self.loadConf()
|
||||
cnt = len(self.mw.col.decks.didsForConf(conf))
|
||||
if cnt > 1:
|
||||
txt = _(
|
||||
"Your changes will affect multiple decks. If you wish to "
|
||||
"change only the current deck, please add a new options group first."
|
||||
)
|
||||
txt = tr(TR.SCHEDULING_YOUR_CHANGES_WILL_AFFECT_MULTIPLE_DECKS)
|
||||
else:
|
||||
txt = ""
|
||||
self.form.count.setText(txt)
|
||||
|
|
|
@ -123,13 +123,7 @@ class DeckConf(QDialog):
|
|||
if not self.saveConf():
|
||||
return
|
||||
if not self.mw.col.sched.rebuild_filtered_deck(self.deck["id"]):
|
||||
if askUser(
|
||||
_(
|
||||
"""\
|
||||
The provided search did not match any cards. Would you like to revise \
|
||||
it?"""
|
||||
)
|
||||
):
|
||||
if askUser(tr(TR.DECKS_THE_PROVIDED_SEARCH_DID_NOT_MATCH)):
|
||||
return
|
||||
self.mw.reset()
|
||||
QDialog.accept(self)
|
||||
|
|
|
@ -658,20 +658,9 @@ class Editor:
|
|||
# check that the model is set up for cloze deletion
|
||||
if not re.search("{{(.*:)*cloze:", self.note.model()["tmpls"][0]["qfmt"]):
|
||||
if self.addMode:
|
||||
tooltip(
|
||||
_(
|
||||
"Warning, cloze deletions will not work until "
|
||||
"you switch the type at the top to Cloze."
|
||||
)
|
||||
)
|
||||
tooltip(tr(TR.EDITING_WARNING_CLOZE_DELETIONS_WILL_NOT_WORK))
|
||||
else:
|
||||
showInfo(
|
||||
_(
|
||||
"""\
|
||||
To make a cloze deletion on an existing note, you need to change it \
|
||||
to a cloze type first, via 'Notes>Change Note Type'"""
|
||||
)
|
||||
)
|
||||
showInfo(tr(TR.EDITING_TO_MAKE_A_CLOZE_DELETION_ON))
|
||||
return
|
||||
# find the highest existing cloze
|
||||
highest = 0
|
||||
|
|
|
@ -65,10 +65,7 @@ class ErrorHandler(QObject):
|
|||
self.timer.start()
|
||||
|
||||
def tempFolderMsg(self):
|
||||
return _(
|
||||
"""Unable to access Anki media folder. The permissions on \
|
||||
your system's temporary folder may be incorrect."""
|
||||
)
|
||||
return tr(TR.QT_MISC_UNABLE_TO_ACCESS_ANKI_MEDIA_FOLDER)
|
||||
|
||||
def onTimeout(self):
|
||||
error = html.escape(self.pool)
|
||||
|
@ -79,12 +76,7 @@ your system's temporary folder may be incorrect."""
|
|||
if "10013" in error:
|
||||
return showWarning(tr(TR.QT_MISC_YOUR_FIREWALL_OR_ANTIVIRUS_PROGRAM_IS))
|
||||
if "no default input" in error.lower():
|
||||
return showWarning(
|
||||
_(
|
||||
"Please connect a microphone, and ensure "
|
||||
"other programs are not using the audio device."
|
||||
)
|
||||
)
|
||||
return showWarning(tr(TR.QT_MISC_PLEASE_CONNECT_A_MICROPHONE_AND_ENSURE))
|
||||
if "invalidTempFolder" in error:
|
||||
return showWarning(self.tempFolderMsg())
|
||||
if "Beautiful Soup is not an HTTP client" in error:
|
||||
|
|
|
@ -12,7 +12,6 @@ from typing import List, Optional
|
|||
import aqt
|
||||
from anki import hooks
|
||||
from anki.exporting import Exporter, exporters
|
||||
from anki.lang import _, ngettext
|
||||
from aqt.qt import *
|
||||
from aqt.utils import TR, checkInvalidFilename, getSaveFile, showWarning, tooltip, tr
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
import aqt
|
||||
from anki.consts import *
|
||||
from anki.lang import _, ngettext
|
||||
from anki.models import NoteType
|
||||
from anki.rsbackend import TemplateError
|
||||
from aqt import AnkiQt, gui_hooks
|
||||
|
|
|
@ -15,7 +15,6 @@ import anki.importing as importing
|
|||
import aqt.deckchooser
|
||||
import aqt.forms
|
||||
import aqt.modelchooser
|
||||
from anki.lang import _, ngettext
|
||||
from aqt import AnkiQt, gui_hooks
|
||||
from aqt.qt import *
|
||||
from aqt.utils import (
|
||||
|
@ -118,12 +117,7 @@ class ImportDialog(QDialog):
|
|||
def onDelimiter(self):
|
||||
str = (
|
||||
getOnlyText(
|
||||
_(
|
||||
"""\
|
||||
By default, Anki will detect the character between fields, such as
|
||||
a tab, comma, and so on. If Anki is detecting the character incorrectly,
|
||||
you can enter it here. Use \\t to represent tab."""
|
||||
),
|
||||
tr(TR.IMPORTING_BY_DEFAULT_ANKI_WILL_DETECT_THE),
|
||||
self,
|
||||
help="importing",
|
||||
)
|
||||
|
@ -132,10 +126,7 @@ you can enter it here. Use \\t to represent tab."""
|
|||
str = str.replace("\\t", "\t")
|
||||
if len(str) > 1:
|
||||
showWarning(
|
||||
_(
|
||||
"Multi-character separators are not supported. "
|
||||
"Please enter one character only."
|
||||
)
|
||||
tr(TR.IMPORTING_MULTICHARACTER_SEPARATORS_ARE_NOT_SUPPORTED_PLEASE)
|
||||
)
|
||||
return
|
||||
self.hideMapping()
|
||||
|
@ -297,12 +288,7 @@ you can enter it here. Use \\t to represent tab."""
|
|||
|
||||
def showUnicodeWarning():
|
||||
"""Shorthand to show a standard warning."""
|
||||
showWarning(
|
||||
_(
|
||||
"Selected file was not in UTF-8 format. Please see the "
|
||||
"importing section of the manual."
|
||||
)
|
||||
)
|
||||
showWarning(tr(TR.IMPORTING_SELECTED_FILE_WAS_NOT_IN_UTF8))
|
||||
|
||||
|
||||
def onImport(mw):
|
||||
|
@ -390,20 +376,12 @@ def importFile(mw, file):
|
|||
except Exception as e:
|
||||
err = repr(str(e))
|
||||
if "invalidFile" in err:
|
||||
msg = _(
|
||||
"""\
|
||||
Invalid file. Please restore from backup."""
|
||||
)
|
||||
msg = tr(TR.IMPORTING_INVALID_FILE_PLEASE_RESTORE_FROM_BACKUP)
|
||||
showWarning(msg)
|
||||
elif "invalidTempFolder" in err:
|
||||
showWarning(mw.errorHandler.tempFolderMsg())
|
||||
elif "readonly" in err:
|
||||
showWarning(
|
||||
_(
|
||||
"""\
|
||||
Unable to import from a read-only file."""
|
||||
)
|
||||
)
|
||||
showWarning(tr(TR.IMPORTING_UNABLE_TO_IMPORT_FROM_A_READONLY))
|
||||
else:
|
||||
msg = tr(TR.IMPORTING_FAILED_DEBUG_INFO) + "\n"
|
||||
msg += str(traceback.format_exc())
|
||||
|
@ -421,13 +399,7 @@ Unable to import from a read-only file."""
|
|||
|
||||
|
||||
def invalidZipMsg():
|
||||
return _(
|
||||
"""\
|
||||
This file does not appear to be a valid .apkg file. If you're getting this \
|
||||
error from a file downloaded from AnkiWeb, chances are that your download \
|
||||
failed. Please try again, and if the problem persists, please try again \
|
||||
with a different browser."""
|
||||
)
|
||||
return tr(TR.IMPORTING_THIS_FILE_DOES_NOT_APPEAR_TO)
|
||||
|
||||
|
||||
def setupApkgImport(mw, importer):
|
||||
|
@ -441,11 +413,7 @@ def setupApkgImport(mw, importer):
|
|||
# adding
|
||||
return True
|
||||
if not mw.restoringBackup and not askUser(
|
||||
_(
|
||||
"""\
|
||||
This will delete your existing collection and replace it with the data in \
|
||||
the file you're importing. Are you sure?"""
|
||||
),
|
||||
tr(TR.IMPORTING_THIS_WILL_DELETE_YOUR_EXISTING_COLLECTION),
|
||||
msgfunc=QMessageBox.warning,
|
||||
defaultno=True,
|
||||
):
|
||||
|
|
|
@ -29,7 +29,6 @@ from anki import hooks
|
|||
from anki.collection import Collection
|
||||
from anki.decks import Deck
|
||||
from anki.hooks import runHook
|
||||
from anki.lang import _, ngettext
|
||||
from anki.rsbackend import RustBackend
|
||||
from anki.sound import AVTag, SoundOrVideoTag
|
||||
from anki.utils import devMode, ids2str, intTime, isMac, isWin, splitFields
|
||||
|
@ -123,12 +122,7 @@ class AnkiQt(QMainWindow):
|
|||
sys.exit(1)
|
||||
# must call this after ui set up
|
||||
if self.safeMode:
|
||||
tooltip(
|
||||
_(
|
||||
"Shift key was held down. Skipping automatic "
|
||||
"syncing and add-on loading."
|
||||
)
|
||||
)
|
||||
tooltip(tr(TR.QT_MISC_SHIFT_KEY_WAS_HELD_DOWN_SKIPPING))
|
||||
# were we given a file to import?
|
||||
if args and args[0] and not self._isAddon(args[0]):
|
||||
self.onAppMsg(args[0])
|
||||
|
@ -319,11 +313,7 @@ class AnkiQt(QMainWindow):
|
|||
return showWarning(tr(TR.QT_MISC_THERE_MUST_BE_AT_LEAST_ONE))
|
||||
# sure?
|
||||
if not askUser(
|
||||
_(
|
||||
"""\
|
||||
All cards, notes, and media for this profile will be deleted. \
|
||||
Are you sure?"""
|
||||
),
|
||||
tr(TR.QT_MISC_ALL_CARDS_NOTES_AND_MEDIA_FOR),
|
||||
msgfunc=QMessageBox.warning,
|
||||
defaultno=True,
|
||||
):
|
||||
|
@ -333,10 +323,7 @@ Are you sure?"""
|
|||
|
||||
def onOpenBackup(self):
|
||||
if not askUser(
|
||||
_(
|
||||
"""\
|
||||
Replace your collection with an earlier backup?"""
|
||||
),
|
||||
tr(TR.QT_MISC_REPLACE_YOUR_COLLECTION_WITH_AN_EARLIER),
|
||||
msgfunc=QMessageBox.warning,
|
||||
defaultno=True,
|
||||
):
|
||||
|
@ -364,13 +351,7 @@ Replace your collection with an earlier backup?"""
|
|||
self.pendingImport = path
|
||||
self.restoringBackup = True
|
||||
|
||||
showInfo(
|
||||
_(
|
||||
"""\
|
||||
Automatic syncing and backups have been disabled while restoring. To enable them again, \
|
||||
close the profile or restart Anki."""
|
||||
)
|
||||
)
|
||||
showInfo(tr(TR.QT_MISC_AUTOMATIC_SYNCING_AND_BACKUPS_HAVE_BEEN))
|
||||
|
||||
self.onOpenProfile()
|
||||
|
||||
|
@ -568,15 +549,7 @@ close the profile or restart Anki."""
|
|||
self.col = None
|
||||
self.progress.finish()
|
||||
if corrupt:
|
||||
showWarning(
|
||||
_(
|
||||
"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."
|
||||
)
|
||||
)
|
||||
showWarning(tr(TR.QT_MISC_YOUR_COLLECTION_FILE_APPEARS_TO_BE))
|
||||
if not corrupt and not self.restoringBackup:
|
||||
self.backup()
|
||||
|
||||
|
@ -1218,26 +1191,7 @@ title="%s" %s>%s</button>""" % (
|
|||
print("clock is off; ignoring")
|
||||
return
|
||||
diffText = tr(TR.QT_MISC_SECOND, count=diff)
|
||||
warn = (
|
||||
_(
|
||||
"""\
|
||||
In order to ensure your collection works correctly when moved between \
|
||||
devices, Anki requires your computer's internal clock to be set correctly. \
|
||||
The internal clock can be wrong even if your system is showing the correct \
|
||||
local time.
|
||||
|
||||
Please go to the time settings on your computer and check the following:
|
||||
|
||||
- AM/PM
|
||||
- Clock drift
|
||||
- Day, month and year
|
||||
- Timezone
|
||||
- Daylight savings
|
||||
|
||||
Difference to correct time: %s."""
|
||||
)
|
||||
% diffText
|
||||
)
|
||||
warn = tr(TR.QT_MISC_IN_ORDER_TO_ENSURE_YOUR_COLLECTION, val="%s") % diffText
|
||||
showWarning(warn)
|
||||
self.app.closeAllWindows()
|
||||
|
||||
|
@ -1281,13 +1235,7 @@ Difference to correct time: %s."""
|
|||
self._activeWindowOnPlay: Optional[QWidget] = None
|
||||
|
||||
def onOdueInvalid(self):
|
||||
showWarning(
|
||||
_(
|
||||
"""\
|
||||
Invalid property found on card. Please use Tools>Check Database, \
|
||||
and if the problem comes up again, please ask on the support site."""
|
||||
)
|
||||
)
|
||||
showWarning(tr(TR.QT_MISC_INVALID_PROPERTY_FOUND_ON_CARD_PLEASE))
|
||||
|
||||
def _isVideo(self, tag: AVTag) -> bool:
|
||||
if isinstance(tag, SoundOrVideoTag):
|
||||
|
@ -1336,15 +1284,7 @@ and if the problem comes up again, please ask on the support site."""
|
|||
progress_shown = self.progress.busy()
|
||||
if progress_shown:
|
||||
self.progress.finish()
|
||||
ret = askUser(
|
||||
_(
|
||||
"""\
|
||||
The requested change will require a full upload of the database when \
|
||||
you next synchronize your collection. If you have reviews or other changes \
|
||||
waiting on another device that haven't been synchronized here yet, they \
|
||||
will be lost. Continue?"""
|
||||
)
|
||||
)
|
||||
ret = askUser(tr(TR.QT_MISC_THE_REQUESTED_CHANGE_WILL_REQUIRE_A))
|
||||
if progress_shown:
|
||||
self.progress.start()
|
||||
return ret
|
||||
|
@ -1355,15 +1295,7 @@ will be lost. Continue?"""
|
|||
True if confirmed or already modified."""
|
||||
if self.col.schemaChanged():
|
||||
return True
|
||||
return askUser(
|
||||
_(
|
||||
"""\
|
||||
The requested change will require a full upload of the database when \
|
||||
you next synchronize your collection. If you have reviews or other changes \
|
||||
waiting on another device that haven't been synchronized here yet, they \
|
||||
will be lost. Continue?"""
|
||||
)
|
||||
)
|
||||
return askUser(tr(TR.QT_MISC_THE_REQUESTED_CHANGE_WILL_REQUIRE_A))
|
||||
|
||||
# Advanced features
|
||||
##########################################################################
|
||||
|
@ -1603,10 +1535,7 @@ will be lost. Continue?"""
|
|||
# we can't raise the main window while in profile dialog, syncing, etc
|
||||
if buf != "raise":
|
||||
showInfo(
|
||||
_(
|
||||
"""\
|
||||
Please ensure a profile is open and Anki is not busy, then try again."""
|
||||
),
|
||||
tr(TR.QT_MISC_PLEASE_ENSURE_A_PROFILE_IS_OPEN),
|
||||
parent=None,
|
||||
)
|
||||
return None
|
||||
|
|
|
@ -7,7 +7,6 @@ from typing import Any, List, Optional, Sequence
|
|||
import aqt.clayout
|
||||
from anki import stdmodels
|
||||
from anki.backend_pb2 import NoteTypeNameIDUseCount
|
||||
from anki.lang import _, ngettext
|
||||
from anki.models import NoteType
|
||||
from anki.notes import Note
|
||||
from anki.rsbackend import pb
|
||||
|
|
|
@ -183,20 +183,9 @@ class Overview:
|
|||
|
||||
def _desc(self, deck):
|
||||
if deck["dyn"]:
|
||||
desc = _(
|
||||
"""\
|
||||
This is a special deck for studying outside of the normal schedule."""
|
||||
)
|
||||
desc += " " + _(
|
||||
"""\
|
||||
Cards will be automatically returned to their original decks after you review \
|
||||
them."""
|
||||
)
|
||||
desc += " " + _(
|
||||
"""\
|
||||
Deleting this deck from the deck list will return all remaining cards \
|
||||
to their original deck."""
|
||||
)
|
||||
desc = tr(TR.STUDYING_THIS_IS_A_SPECIAL_DECK_FOR)
|
||||
desc += " " + tr(TR.STUDYING_CARDS_WILL_BE_AUTOMATICALLY_RETURNED_TO)
|
||||
desc += " " + tr(TR.STUDYING_DELETING_THIS_DECK_FROM_THE_DECK)
|
||||
else:
|
||||
desc = deck.get("desc", "")
|
||||
if not desc:
|
||||
|
|
|
@ -181,11 +181,7 @@ class Preferences(QDialog):
|
|||
self.form.syncDeauth.setVisible(False)
|
||||
self.form.syncUser.setText("")
|
||||
self.form.syncLabel.setText(
|
||||
_(
|
||||
"""\
|
||||
<b>Synchronization</b><br>
|
||||
Not currently enabled; click the sync button in the main window to enable."""
|
||||
)
|
||||
tr(TR.PREFERENCES_SYNCHRONIZATIONNOT_CURRENTLY_ENABLED_CLICK_THE_SYNC)
|
||||
)
|
||||
|
||||
def onSyncDeauth(self) -> None:
|
||||
|
|
|
@ -253,11 +253,7 @@ class ProfileManager:
|
|||
QMessageBox.warning(
|
||||
None,
|
||||
tr(TR.PROFILES_PROFILE_CORRUPT),
|
||||
_(
|
||||
"""\
|
||||
Anki could not read your profile data. Window sizes and your sync login \
|
||||
details have been forgotten."""
|
||||
),
|
||||
tr(TR.PROFILES_ANKI_COULD_NOT_READ_YOUR_PROFILE),
|
||||
)
|
||||
traceback.print_stack()
|
||||
print("resetting corrupt profile")
|
||||
|
@ -322,14 +318,7 @@ details have been forgotten."""
|
|||
except Exception as e:
|
||||
self.db.rollback()
|
||||
if "WinError 5" in str(e):
|
||||
showWarning(
|
||||
_(
|
||||
"""\
|
||||
Anki could not rename your profile because it could not rename the profile \
|
||||
folder on disk. Please ensure you have permission to write to Documents/Anki \
|
||||
and no other programs are accessing your profile folders, then try again."""
|
||||
)
|
||||
)
|
||||
showWarning(tr(TR.PROFILES_ANKI_COULD_NOT_RENAME_YOUR_PROFILE))
|
||||
else:
|
||||
raise
|
||||
except:
|
||||
|
|
|
@ -14,7 +14,6 @@ from PyQt5.QtCore import Qt
|
|||
|
||||
from anki import hooks
|
||||
from anki.cards import Card
|
||||
from anki.lang import _, ngettext
|
||||
from anki.utils import stripHTML
|
||||
from aqt import AnkiQt, gui_hooks
|
||||
from aqt.qt import *
|
||||
|
@ -388,10 +387,7 @@ class Reviewer:
|
|||
if not self.typeCorrect:
|
||||
if self.typeCorrect is None:
|
||||
if clozeIdx:
|
||||
warn = _(
|
||||
"""\
|
||||
Please run Tools>Empty Cards"""
|
||||
)
|
||||
warn = tr(TR.STUDYING_PLEASE_RUN_TOOLSEMPTY_CARDS)
|
||||
else:
|
||||
warn = tr(TR.STUDYING_TYPE_ANSWER_UNKNOWN_FIELD, val=fld)
|
||||
return re.sub(self.typeAnsPat, warn, buf)
|
||||
|
|
|
@ -3,13 +3,10 @@
|
|||
import glob, re, json, stringcase
|
||||
|
||||
files = (
|
||||
# glob.glob("../../pylib/**/*.py", recursive=True)
|
||||
# glob.glob("../../pylib/**/*.py", recursive=True) +
|
||||
glob.glob("../../qt/**/*.py", recursive=True)
|
||||
# glob.glob("../../qt/**/forms/*.ui", recursive=True)
|
||||
)
|
||||
string_re = re.compile(
|
||||
r'ngettext\(\s*"(.+?)",\s+".+?",\s+(.+?)\s*,?\s*\)\s+%\s+\2', re.DOTALL
|
||||
)
|
||||
string_re = re.compile(r'_\(\s*(".*?")\s*\)', re.DOTALL)
|
||||
|
||||
map = json.load(open("keys_by_text.json"))
|
||||
|
||||
|
@ -18,67 +15,29 @@ blacklist = {
|
|||
"Label1",
|
||||
"After pressing OK, you can choose which tags to include.",
|
||||
"Filter/Cram",
|
||||
"Show %s",
|
||||
"~",
|
||||
"about:blank",
|
||||
"%d card imported.",
|
||||
# need to update manually
|
||||
"Browse (%(cur)d card shown; %(sel)s)",
|
||||
# previewer.py needs updating to fix these
|
||||
"Shortcut key: R",
|
||||
"Shortcut key: B",
|
||||
}
|
||||
|
||||
from html.entities import name2codepoint
|
||||
|
||||
reEnts = re.compile(r"&#?\w+;")
|
||||
|
||||
|
||||
def decode_ents(html):
|
||||
def fixup(m):
|
||||
text = m.group(0)
|
||||
if text[:2] == "&#":
|
||||
# character reference
|
||||
try:
|
||||
if text[:3] == "&#x":
|
||||
return chr(int(text[3:-1], 16))
|
||||
else:
|
||||
return chr(int(text[2:-1]))
|
||||
except ValueError:
|
||||
pass
|
||||
else:
|
||||
# named entity
|
||||
try:
|
||||
text = chr(name2codepoint[text[1:-1]])
|
||||
except KeyError:
|
||||
pass
|
||||
return text # leave as is
|
||||
|
||||
return reEnts.sub(fixup, html)
|
||||
|
||||
|
||||
def munge_key(key):
|
||||
if key == "browsing-note":
|
||||
return "browsing-note-count"
|
||||
if key == "card-templates-card":
|
||||
return "card-templates-card-count"
|
||||
return key
|
||||
|
||||
|
||||
def repl(m):
|
||||
print(m.group(0))
|
||||
text = decode_ents(m.group(1))
|
||||
# the argument may consistent of multiple strings that need merging together
|
||||
text = eval("(" + m.group(1) + ")")
|
||||
print(f"text is `{text}`")
|
||||
|
||||
if text in blacklist:
|
||||
return m.group(0)
|
||||
|
||||
(module, key) = map[text]
|
||||
key = munge_key(key)
|
||||
|
||||
screaming = stringcase.constcase(key)
|
||||
print(screaming)
|
||||
|
||||
ret = f"tr(TR.{screaming}, count={m.group(2)})"
|
||||
print(ret)
|
||||
return ret
|
||||
if "%d" in text or "%s" in text:
|
||||
# replace { $val } with %s for compat with old code
|
||||
return f'tr(TR.{screaming}, val="%s")'
|
||||
|
||||
return f"tr(TR.{screaming})"
|
||||
|
||||
|
||||
for file in files:
|
||||
|
|
Loading…
Reference in a new issue