diff --git a/pylib/anki/_backend/__init__.py b/pylib/anki/_backend/__init__.py index a8d1ca989..ec233f8ea 100644 --- a/pylib/anki/_backend/__init__.py +++ b/pylib/anki/_backend/__init__.py @@ -122,7 +122,7 @@ class Translations(GeneratedTranslations): self._backend = backend def __call__(self, *args: Any, **kwargs: Any) -> str: - "Mimic the old col.tr(TR....) interface" + "Mimic the old col.tr / TR interface" return self._backend().translate(*args, **kwargs) def _translate( diff --git a/pylib/anki/collection.py b/pylib/anki/collection.py index ed8e22be9..710d4834e 100644 --- a/pylib/anki/collection.py +++ b/pylib/anki/collection.py @@ -818,7 +818,7 @@ table.review-log {{ {revlog_style} }} return UndoStatus() if isinstance(self._undo, _ReviewsUndo): - return UndoStatus(undo=self.tr(TR.SCHEDULING_REVIEW)) + return UndoStatus(undo=self.tr.scheduling_review()) elif isinstance(self._undo, Checkpoint): return UndoStatus(undo=self._undo.name) else: @@ -975,7 +975,7 @@ table.review-log {{ {revlog_style} }} try: problems = list(self._backend.check_database()) ok = not problems - problems.append(self.tr(TR.DATABASE_CHECK_REBUILT)) + problems.append(self.tr.database_check_rebuilt()) except DBError as e: problems = [str(e.args[0])] ok = False diff --git a/pylib/anki/decks.py b/pylib/anki/decks.py index af402b778..a39513a87 100644 --- a/pylib/anki/decks.py +++ b/pylib/anki/decks.py @@ -405,7 +405,7 @@ class DeckManager: deck = self.get(did, default=default) if deck: return deck["name"] - return self.col.tr(TR.DECKS_NO_DECK) + return self.col.tr.decks_no_deck() def name_if_exists(self, did: DeckID) -> Optional[str]: deck = self.get(did, default=False) diff --git a/pylib/anki/exporting.py b/pylib/anki/exporting.py index f169dfb91..4b851ad93 100644 --- a/pylib/anki/exporting.py +++ b/pylib/anki/exporting.py @@ -15,7 +15,6 @@ from anki import hooks from anki.cards import CardID from anki.collection import Collection from anki.decks import DeckID -from anki.lang import TR from anki.utils import ids2str, namedtmp, splitFields, stripHTML @@ -105,7 +104,7 @@ class TextCardExporter(Exporter): @staticmethod def key(col: Collection) -> str: - return col.tr(TR.EXPORTING_CARDS_IN_PLAIN_TEXT) + return col.tr.exporting_cards_in_plain_text() def doExport(self, file) -> None: ids = sorted(self.cardIds()) @@ -140,7 +139,7 @@ class TextNoteExporter(Exporter): @staticmethod def key(col: Collection) -> str: - return col.tr(TR.EXPORTING_NOTES_IN_PLAIN_TEXT) + return col.tr.exporting_notes_in_plain_text() def doExport(self, file: BufferedWriter) -> None: cardIds = self.cardIds() @@ -184,7 +183,7 @@ class AnkiExporter(Exporter): @staticmethod def key(col: Collection) -> str: - return col.tr(TR.EXPORTING_ANKI_20_DECK) + return col.tr.exporting_anki_20_deck() def deckIds(self) -> List[DeckID]: if self.cids: @@ -333,7 +332,7 @@ class AnkiPackageExporter(AnkiExporter): @staticmethod def key(col: Collection) -> str: - return col.tr(TR.EXPORTING_ANKI_DECK_PACKAGE) + return col.tr.exporting_anki_deck_package() def exportInto(self, path: str) -> None: # open a zip file @@ -420,7 +419,7 @@ class AnkiCollectionPackageExporter(AnkiPackageExporter): @staticmethod def key(col: Collection) -> str: - return col.tr(TR.EXPORTING_ANKI_COLLECTION_PACKAGE) + return col.tr.exporting_anki_collection_package() def doExport(self, z, path): "Export collection. Caller must re-open afterwards." diff --git a/pylib/anki/importing/anki2.py b/pylib/anki/importing/anki2.py index bf92198d4..4cb4e9853 100644 --- a/pylib/anki/importing/anki2.py +++ b/pylib/anki/importing/anki2.py @@ -168,16 +168,16 @@ class Anki2Importer(Importer): if dupesIgnored: for row in dupesIgnored: - self._logNoteRow(self.dst.tr(TR.IMPORTING_SKIPPED), row) + self._logNoteRow(self.dst.tr.importing_skipped(), row) if update: for row in update: - self._logNoteRow(self.dst.tr(TR.IMPORTING_UPDATED), row) + self._logNoteRow(self.dst.tr.importing_updated(), row) if add: for row in add: - self._logNoteRow(self.dst.tr(TR.ADDING_ADDED), row) + self._logNoteRow(self.dst.tr.adding_added(), row) if dupesIdentical: for row in dupesIdentical: - self._logNoteRow(self.dst.tr(TR.IMPORTING_IDENTICAL), row) + self._logNoteRow(self.dst.tr.importing_identical(), row) # export info for calling code self.dupes = len(dupesIdentical) diff --git a/pylib/anki/importing/mnemo.py b/pylib/anki/importing/mnemo.py index f3cafedbd..5e0ca41bf 100644 --- a/pylib/anki/importing/mnemo.py +++ b/pylib/anki/importing/mnemo.py @@ -22,7 +22,7 @@ class MnemosyneImporter(NoteImporter): ver = db.scalar("select value from global_variables where key='version'") if not ver.startswith("Mnemosyne SQL 1") and ver not in ("2", "3"): self.log.append( - self.col.tr(TR.IMPORTING_FILE_VERSION_UNKNOWN_TRYING_IMPORT_ANYWAY) + self.col.tr.importing_file_version_unknown_trying_import_anyway() ) # gather facts into temp objects curid = None diff --git a/pylib/anki/latex.py b/pylib/anki/latex.py index e7bab9dce..7b6e2c0f5 100644 --- a/pylib/anki/latex.py +++ b/pylib/anki/latex.py @@ -174,7 +174,7 @@ def _errMsg(col: anki.collection.Collection, type: str, texpath: str) -> Any: raise Exception() msg += f"
{html.escape(log)}
" except: - msg += col.tr(TR.MEDIA_HAVE_YOU_INSTALLED_LATEX_AND_DVIPNGDVISVGM) + msg += col.tr.media_have_you_installed_latex_and_dvipngdvisvgm() return msg diff --git a/pylib/anki/scheduler/v2.py b/pylib/anki/scheduler/v2.py index 2b644b5da..c3d5524b9 100644 --- a/pylib/anki/scheduler/v2.py +++ b/pylib/anki/scheduler/v2.py @@ -1133,7 +1133,7 @@ and (queue={QUEUE_TYPE_NEW} or (queue={QUEUE_TYPE_REV} and due<=?))""", "Return the next interval for CARD as a string." ivl_secs = self.nextIvl(card, ease) if not ivl_secs: - return self.col.tr(TR.SCHEDULING_END) + return self.col.tr.scheduling_end() s = self.col.format_timespan(ivl_secs, FormatTimeSpan.ANSWER_BUTTONS) if ivl_secs < self.col.conf["collapseTime"]: s = "<" + s diff --git a/pylib/tests/test_collection.py b/pylib/tests/test_collection.py index 1a0c64822..81d790628 100644 --- a/pylib/tests/test_collection.py +++ b/pylib/tests/test_collection.py @@ -151,7 +151,7 @@ def test_translate(): no_uni = without_unicode_isolation assert ( - col.tr(TR.CARD_TEMPLATE_RENDERING_FRONT_SIDE_PROBLEM) + col.tr.card_template_rendering_front_side_problem() == "Front template has a problem:" ) assert no_uni(col.tr(TR.STATISTICS_REVIEWS, reviews=1)) == "1 review" diff --git a/pylib/tools/BUILD.bazel b/pylib/tools/BUILD.bazel index 3e7f6c9e6..3c97bdc7c 100644 --- a/pylib/tools/BUILD.bazel +++ b/pylib/tools/BUILD.bazel @@ -46,6 +46,17 @@ py_binary( ], ) +py_binary( + name = "rewrite_tr", + srcs = [ + "rewrite_tr.py", + ], + tags = ["manual"], + deps = [ + requirement("stringcase"), + ], +) + filegroup( name = "py_source_files", srcs = glob(["*.py"]), diff --git a/pylib/tools/rewrite_tr.py b/pylib/tools/rewrite_tr.py new file mode 100644 index 000000000..875bdf5ac --- /dev/null +++ b/pylib/tools/rewrite_tr.py @@ -0,0 +1,41 @@ +# Copyright: Ankitects Pty Ltd and contributors +# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html + +from __future__ import annotations + +import os +import re +from re import Match + +import stringcase + +TR_REF = re.compile(r"\.tr\(TR.([^,)]+)\)") + + +def repl(m: Match) -> str: + name = m.group(1).lower() + return f".tr.{name}()" + + +def update_py(path: str) -> None: + buf = [] + changed = False + for line in open(path): + line2 = TR_REF.sub(repl, line) + if line != line2: + buf.append(line2) + changed = True + else: + buf.append(line) + + if changed: + open(path, "w").writelines(buf) + print("updated", path) + + +for dirpath, dirnames, fnames in os.walk(os.environ["BUILD_WORKSPACE_DIRECTORY"]): + if "bazel-" in dirpath: + continue + for fname in fnames: + if fname.endswith(".py"): + update_py(os.path.join(dirpath, fname)) diff --git a/qt/aqt/sidebar.py b/qt/aqt/sidebar.py index 10e1bb67d..bbf6cd3b1 100644 --- a/qt/aqt/sidebar.py +++ b/qt/aqt/sidebar.py @@ -307,7 +307,7 @@ class SidebarToolbar(QToolBar): class SidebarSearchBar(QLineEdit): def __init__(self, sidebar: SidebarTreeView) -> None: QLineEdit.__init__(self, sidebar) - self.setPlaceholderText(sidebar.col.tr(TR.BROWSING_SIDEBAR_FILTER)) + self.setPlaceholderText(sidebar.col.tr.browsing_sidebar_filter()) self.sidebar = sidebar self.timer = QTimer(self) self.timer.setInterval(600)