diff --git a/pylib/anki/rsbackend.py b/pylib/anki/rsbackend.py
index eccfabfab..cdd9d9603 100644
--- a/pylib/anki/rsbackend.py
+++ b/pylib/anki/rsbackend.py
@@ -12,7 +12,7 @@ import ankirspy # pytype: disable=import-error
import anki.backend_pb2 as pb
import anki.buildinfo
from anki import hooks
-from anki.fluent_pb2 import FluentString as FString
+from anki.fluent_pb2 import FluentString as TR
from anki.models import AllTemplateReqs
from anki.sound import AVTag, SoundOrVideoTag, TTSTag
from anki.types import assert_impossible_literal
@@ -324,7 +324,7 @@ class RustBackend:
pb.BackendInput(trash_media_files=pb.TrashMediaFilesIn(fnames=fnames))
)
- def translate(self, key: FString, **kwargs: Union[str, int, float]):
+ def translate(self, key: TR, **kwargs: Union[str, int, float]):
return self._run_command(
pb.BackendInput(translate_string=translate_string_in(key, **kwargs))
).translate_string
@@ -358,7 +358,7 @@ class RustBackend:
def translate_string_in(
- key: FString, **kwargs: Union[str, int, float]
+ key: TR, **kwargs: Union[str, int, float]
) -> pb.TranslateStringIn:
args = {}
for (k, v) in kwargs.items():
@@ -376,7 +376,7 @@ class I18nBackend:
)
self._backend = ankirspy.open_i18n(init_msg.SerializeToString())
- def translate(self, key: FString, **kwargs: Union[str, int, float]):
+ def translate(self, key: TR, **kwargs: Union[str, int, float]):
return self._backend.translate(
translate_string_in(key, **kwargs).SerializeToString()
)
diff --git a/pylib/anki/stats.py b/pylib/anki/stats.py
index 5be72f04a..d336b6b61 100644
--- a/pylib/anki/stats.py
+++ b/pylib/anki/stats.py
@@ -11,7 +11,7 @@ from typing import Any, Dict, List, Optional, Tuple
import anki
from anki.consts import *
from anki.lang import _, ngettext
-from anki.rsbackend import FormatTimeSpanContext, FString
+from anki.rsbackend import TR, FormatTimeSpanContext
from anki.utils import ids2str
# Card stats
@@ -48,7 +48,7 @@ class CardStats:
next = self.date(next)
if next:
self.addLine(
- self.col.backend.translate(FString.STATISTICS_DUE_DATE), next,
+ self.col.backend.translate(TR.STATISTICS_DUE_DATE), next,
)
if c.queue == QUEUE_TYPE_REV:
self.addLine(
@@ -280,7 +280,7 @@ from revlog where id > ? """
self._line(
i,
_("Total"),
- self.col.backend.translate(FString.STATISTICS_REVIEWS, reviews=tot),
+ self.col.backend.translate(TR.STATISTICS_REVIEWS, reviews=tot),
)
self._line(i, _("Average"), self._avgDay(tot, num, _("reviews")))
tomorrow = self.col.db.scalar(
@@ -458,7 +458,7 @@ group by day order by day"""
i,
_("Average answer time"),
self.col.backend.translate(
- FString.STATISTICS_AVERAGE_ANSWER_TIME,
+ TR.STATISTICS_AVERAGE_ANSWER_TIME,
**{"cards-per-minute": perMin, "average-seconds": average_secs},
),
)
diff --git a/pylib/tests/test_collection.py b/pylib/tests/test_collection.py
index acba9f139..734ca5fa9 100644
--- a/pylib/tests/test_collection.py
+++ b/pylib/tests/test_collection.py
@@ -5,7 +5,7 @@ import tempfile
from anki import Collection as aopen
from anki.lang import without_unicode_isolation
-from anki.rsbackend import FString
+from anki.rsbackend import TR
from anki.stdmodels import addBasicModel, models
from anki.utils import isWin
from tests.shared import assertException, getEmptyCol
@@ -157,8 +157,8 @@ def test_translate():
no_uni = without_unicode_isolation
assert (
- tr(FString.CARD_TEMPLATE_RENDERING_FRONT_SIDE_PROBLEM)
+ tr(TR.CARD_TEMPLATE_RENDERING_FRONT_SIDE_PROBLEM)
== "Front template has a problem:"
)
- assert no_uni(tr(FString.STATISTICS_REVIEWS, reviews=1)) == "1 review"
- assert no_uni(tr(FString.STATISTICS_REVIEWS, reviews=2)) == "2 reviews"
+ assert no_uni(tr(TR.STATISTICS_REVIEWS, reviews=1)) == "1 review"
+ assert no_uni(tr(TR.STATISTICS_REVIEWS, reviews=2)) == "2 reviews"
diff --git a/qt/aqt/browser.py b/qt/aqt/browser.py
index ea2b7657d..4a1f7b317 100644
--- a/qt/aqt/browser.py
+++ b/qt/aqt/browser.py
@@ -24,7 +24,7 @@ from anki.consts import *
from anki.lang import _, ngettext
from anki.models import NoteType
from anki.notes import Note
-from anki.rsbackend import FString
+from anki.rsbackend import TR
from anki.utils import htmlToTextLine, ids2str, intTime, isMac, isWin
from aqt import AnkiQt, gui_hooks
from aqt.editor import Editor
@@ -356,7 +356,7 @@ class DataModel(QAbstractTableModel):
elif c.queue == QUEUE_TYPE_LRN:
date = c.due
elif c.queue == QUEUE_TYPE_NEW or c.type == CARD_TYPE_NEW:
- return tr(FString.STATISTICS_DUE_FOR_NEW_CARD, number=c.due)
+ return tr(TR.STATISTICS_DUE_FOR_NEW_CARD, number=c.due)
elif c.queue in (QUEUE_TYPE_REV, QUEUE_TYPE_DAY_LEARN_RELEARN) or (
c.type == CARD_TYPE_REV and c.queue < 0
):
@@ -730,7 +730,7 @@ class Browser(QMainWindow):
("noteCrt", _("Created")),
("noteMod", _("Edited")),
("cardMod", _("Changed")),
- ("cardDue", tr(FString.STATISTICS_DUE_DATE)),
+ ("cardDue", tr(TR.STATISTICS_DUE_DATE)),
("cardIvl", _("Interval")),
("cardEase", _("Ease")),
("cardReps", _("Reviews")),
@@ -1281,7 +1281,7 @@ by clicking on one on the left."""
(_("New"), "is:new"),
(_("Learning"), "is:learn"),
(_("Review"), "is:review"),
- (tr(FString.FILTERING_IS_DUE), "is:due"),
+ (tr(TR.FILTERING_IS_DUE), "is:due"),
None,
(_("Suspended"), "is:suspended"),
(_("Buried"), "is:buried"),
diff --git a/qt/aqt/deckbrowser.py b/qt/aqt/deckbrowser.py
index 184ccd59e..e1b3cd748 100644
--- a/qt/aqt/deckbrowser.py
+++ b/qt/aqt/deckbrowser.py
@@ -11,7 +11,7 @@ from typing import Any
import aqt
from anki.errors import DeckRenameError
from anki.lang import _, ngettext
-from anki.rsbackend import FString
+from anki.rsbackend import TR
from anki.utils import ids2str
from aqt import AnkiQt, gui_hooks
from aqt.qt import *
@@ -185,7 +185,7 @@ where id > ?""",
%s | %s |
%s | |
""" % (
_("Deck"),
- tr(FString.STATISTICS_DUE_COUNT),
+ tr(TR.STATISTICS_DUE_COUNT),
_("New"),
)
buf += self._topLevelDragRow()
diff --git a/qt/aqt/errors.py b/qt/aqt/errors.py
index b40dd18ff..1bbc3b1da 100644
--- a/qt/aqt/errors.py
+++ b/qt/aqt/errors.py
@@ -11,7 +11,7 @@ from markdown import markdown
from anki.lang import _
from aqt import mw
from aqt.qt import *
-from aqt.utils import FString, showText, showWarning, supportText, tr
+from aqt.utils import TR, showText, showWarning, supportText, tr
if not os.environ.get("DEBUG"):
@@ -106,14 +106,14 @@ your system's temporary folder may be incorrect."""
)
)
if "disk I/O error" in error:
- showWarning(markdown(tr(FString.ERRORS_ACCESSING_DB)))
+ showWarning(markdown(tr(TR.ERRORS_ACCESSING_DB)))
return
if self.mw.addonManager.dirty:
- txt = markdown(tr(FString.ERRORS_ADDONS_ACTIVE_POPUP))
+ txt = markdown(tr(TR.ERRORS_ADDONS_ACTIVE_POPUP))
error = supportText() + self._addonText(error) + "\n" + error
else:
- txt = markdown(tr(FString.ERRORS_STANDARD_POPUP))
+ txt = markdown(tr(TR.ERRORS_STANDARD_POPUP))
error = supportText() + "\n" + error
# show dialog
diff --git a/qt/aqt/mediacheck.py b/qt/aqt/mediacheck.py
index 20e36a178..7500ceafd 100644
--- a/qt/aqt/mediacheck.py
+++ b/qt/aqt/mediacheck.py
@@ -10,13 +10,7 @@ from typing import Iterable, List, Optional, TypeVar
import aqt
from anki import hooks
-from anki.rsbackend import (
- FString,
- Interrupted,
- MediaCheckOutput,
- Progress,
- ProgressKind,
-)
+from anki.rsbackend import TR, Interrupted, MediaCheckOutput, Progress, ProgressKind
from aqt.qt import *
from aqt.utils import askUser, restoreGeom, saveGeom, showText, tooltip, tr
@@ -89,14 +83,14 @@ class MediaChecker:
layout.addWidget(box)
if output.unused:
- b = QPushButton(tr(FString.MEDIA_CHECK_DELETE_UNUSED))
+ b = QPushButton(tr(TR.MEDIA_CHECK_DELETE_UNUSED))
b.setAutoDefault(False)
box.addButton(b, QDialogButtonBox.RejectRole)
b.clicked.connect(lambda c: self._on_trash_files(output.unused)) # type: ignore
if output.missing:
if any(map(lambda x: x.startswith("latex-"), output.missing)):
- b = QPushButton(tr(FString.MEDIA_CHECK_RENDER_LATEX))
+ b = QPushButton(tr(TR.MEDIA_CHECK_RENDER_LATEX))
b.setAutoDefault(False)
box.addButton(b, QDialogButtonBox.RejectRole)
b.clicked.connect(self._on_render_latex) # type: ignore
@@ -125,17 +119,17 @@ class MediaChecker:
browser.onSearchActivated()
showText(err, type="html")
else:
- tooltip(tr(FString.MEDIA_CHECK_ALL_LATEX_RENDERED))
+ tooltip(tr(TR.MEDIA_CHECK_ALL_LATEX_RENDERED))
def _on_render_latex_progress(self, count: int) -> bool:
if self.progress_dialog.wantCancel:
return False
- self.mw.progress.update(tr(FString.MEDIA_CHECK_CHECKED, count=count))
+ self.mw.progress.update(tr(TR.MEDIA_CHECK_CHECKED, count=count))
return True
def _on_trash_files(self, fnames: List[str]):
- if not askUser(tr(FString.MEDIA_CHECK_DELETE_UNUSED_CONFIRM)):
+ if not askUser(tr(TR.MEDIA_CHECK_DELETE_UNUSED_CONFIRM)):
return
self.progress_dialog = self.mw.progress.start()
@@ -149,10 +143,10 @@ class MediaChecker:
remaining -= len(chunk)
if time.time() - last_progress >= 0.3:
self.mw.progress.update(
- tr(FString.MEDIA_CHECK_FILES_REMAINING, count=remaining)
+ tr(TR.MEDIA_CHECK_FILES_REMAINING, count=remaining)
)
finally:
self.mw.progress.finish()
self.progress_dialog = None
- tooltip(tr(FString.MEDIA_CHECK_DELETE_UNUSED_COMPLETE, count=total))
+ tooltip(tr(TR.MEDIA_CHECK_DELETE_UNUSED_COMPLETE, count=total))
diff --git a/qt/aqt/mediasync.py b/qt/aqt/mediasync.py
index 889eec80a..f0b46647a 100644
--- a/qt/aqt/mediasync.py
+++ b/qt/aqt/mediasync.py
@@ -10,13 +10,7 @@ from typing import List, Union
import aqt
from anki import hooks
-from anki.rsbackend import (
- FString,
- Interrupted,
- MediaSyncProgress,
- Progress,
- ProgressKind,
-)
+from anki.rsbackend import TR, Interrupted, MediaSyncProgress, Progress, ProgressKind
from anki.types import assert_impossible
from anki.utils import intTime
from aqt import gui_hooks
@@ -63,10 +57,10 @@ class MediaSyncer:
return
if not self.mw.pm.media_syncing_enabled():
- self._log_and_notify(tr(FString.SYNC_MEDIA_DISABLED))
+ self._log_and_notify(tr(TR.SYNC_MEDIA_DISABLED))
return
- self._log_and_notify(tr(FString.SYNC_MEDIA_STARTING))
+ self._log_and_notify(tr(TR.SYNC_MEDIA_STARTING))
self._syncing = True
self._want_stop = False
gui_hooks.media_sync_did_start_or_stop(True)
@@ -99,14 +93,14 @@ class MediaSyncer:
if exc is not None:
self._handle_sync_error(exc)
else:
- self._log_and_notify(tr(FString.SYNC_MEDIA_COMPLETE))
+ self._log_and_notify(tr(TR.SYNC_MEDIA_COMPLETE))
def _handle_sync_error(self, exc: BaseException):
if isinstance(exc, Interrupted):
- self._log_and_notify(tr(FString.SYNC_MEDIA_ABORTED))
+ self._log_and_notify(tr(TR.SYNC_MEDIA_ABORTED))
return
- self._log_and_notify(tr(FString.SYNC_MEDIA_FAILED))
+ self._log_and_notify(tr(TR.SYNC_MEDIA_FAILED))
showWarning(str(exc))
def entries(self) -> List[LogEntryWithTime]:
@@ -115,7 +109,7 @@ class MediaSyncer:
def abort(self) -> None:
if not self.is_syncing():
return
- self._log_and_notify(tr(FString.SYNC_MEDIA_ABORTING))
+ self._log_and_notify(tr(TR.SYNC_MEDIA_ABORTING))
self._want_stop = True
def is_syncing(self) -> bool:
@@ -158,8 +152,8 @@ class MediaSyncDialog(QDialog):
self._close_when_done = close_when_done
self.form = aqt.forms.synclog.Ui_Dialog()
self.form.setupUi(self)
- self.setWindowTitle(tr(FString.SYNC_MEDIA_LOG_TITLE))
- self.abort_button = QPushButton(tr(FString.SYNC_ABORT_BUTTON))
+ self.setWindowTitle(tr(TR.SYNC_MEDIA_LOG_TITLE))
+ self.abort_button = QPushButton(tr(TR.SYNC_ABORT_BUTTON))
self.abort_button.clicked.connect(self._on_abort) # type: ignore
self.abort_button.setAutoDefault(False)
self.form.buttonBox.addButton(self.abort_button, QDialogButtonBox.ActionRole)
diff --git a/qt/aqt/preferences.py b/qt/aqt/preferences.py
index 81170f681..5b997724f 100644
--- a/qt/aqt/preferences.py
+++ b/qt/aqt/preferences.py
@@ -10,7 +10,7 @@ import aqt
from anki.lang import _
from aqt import AnkiQt
from aqt.qt import *
-from aqt.utils import askUser, openHelp, showInfo, showWarning, tr, FString
+from aqt.utils import TR, askUser, openHelp, showInfo, showWarning, tr
class Preferences(QDialog):
@@ -177,7 +177,7 @@ class Preferences(QDialog):
######################################################################
def setupNetwork(self):
- self.form.media_log.setText(tr(FString.SYNC_MEDIA_LOG_BUTTON))
+ self.form.media_log.setText(tr(TR.SYNC_MEDIA_LOG_BUTTON))
self.form.media_log.clicked.connect(self.on_media_log)
self.form.syncOnProgramOpen.setChecked(self.prof["autoSync"])
self.form.syncMedia.setChecked(self.prof["syncMedia"])
diff --git a/qt/aqt/utils.py b/qt/aqt/utils.py
index 26cc4fa5e..a0e123622 100644
--- a/qt/aqt/utils.py
+++ b/qt/aqt/utils.py
@@ -13,7 +13,7 @@ from typing import Any, Optional, Union
import anki
import aqt
from anki.lang import _
-from anki.rsbackend import FString
+from anki.rsbackend import TR
from anki.utils import invalidFilename, isMac, isWin, noBundledLibs, versionWithBuild
from aqt.qt import *
from aqt.theme import theme_manager
@@ -32,7 +32,7 @@ def locale_dir() -> str:
return os.path.join(aqt_data_folder(), "locale")
-def tr(key: FString, **kwargs: Union[str, int, float]) -> str:
+def tr(key: TR, **kwargs: Union[str, int, float]) -> str:
"Shortcut to access Fluent translations."
return anki.lang.current_i18n.translate(key, **kwargs)
diff --git a/qt/tests/test_i18n.py b/qt/tests/test_i18n.py
index edff4dc87..c11180032 100644
--- a/qt/tests/test_i18n.py
+++ b/qt/tests/test_i18n.py
@@ -1,13 +1,13 @@
import anki.lang
-from anki.rsbackend import FString
+from anki.rsbackend import TR
def test_no_collection_i18n():
anki.lang.set_lang("zz", "")
tr2 = anki.lang.current_i18n.translate
no_uni = anki.lang.without_unicode_isolation
- assert no_uni(tr2(FString.STATISTICS_REVIEWS, reviews=2)) == "2 reviews"
+ assert no_uni(tr2(TR.STATISTICS_REVIEWS, reviews=2)) == "2 reviews"
anki.lang.set_lang("ja", "")
tr2 = anki.lang.current_i18n.translate
- assert no_uni(tr2(FString.STATISTICS_REVIEWS, reviews=2)) == "2 枚の復習カード"
+ assert no_uni(tr2(TR.STATISTICS_REVIEWS, reviews=2)) == "2 枚の復習カード"