drop the separate i18n backend

This commit is contained in:
Damien Elmes 2020-03-14 09:45:00 +10:00
parent 874bc085fe
commit ba17567617
6 changed files with 31 additions and 106 deletions

View File

@ -145,7 +145,7 @@ current_catalog: Optional[
] = None
# the current Fluent translation instance
current_i18n: Optional[anki.rsbackend.I18nBackend]
current_i18n: Optional[anki.rsbackend.RustBackend]
# path to locale folder
locale_folder = ""
@ -175,9 +175,9 @@ def set_lang(lang: str, locale_dir: str) -> None:
current_catalog = gettext.translation(
"anki", gettext_dir, languages=[lang], fallback=True
)
current_i18n = anki.rsbackend.I18nBackend(
preferred_langs=[lang], ftl_folder=ftl_dir
)
current_i18n = anki.rsbackend.RustBackend(ftl_folder=ftl_dir, langs=[lang])
locale_folder = locale_dir

View File

@ -200,12 +200,20 @@ def _on_progress(progress_bytes: bytes) -> bool:
class RustBackend:
def __init__(self, server: bool = False) -> None:
ftl_folder = os.path.join(anki.lang.locale_folder, "fluent")
def __init__(
self,
ftl_folder: Optional[str] = None,
langs: Optional[List[str]] = None,
server: bool = False,
) -> None:
# pick up global defaults if not provided
if ftl_folder is None:
ftl_folder = os.path.join(anki.lang.locale_folder, "fluent")
if langs is None:
langs = [anki.lang.currentLang]
init_msg = pb.BackendInit(
locale_folder_path=ftl_folder,
preferred_langs=[anki.lang.currentLang],
server=server,
locale_folder_path=ftl_folder, preferred_langs=langs, server=server,
)
self._backend = ankirspy.open_backend(init_msg.SerializeToString())
self._backend.set_progress_callback(_on_progress)
@ -428,19 +436,6 @@ def translate_string_in(
return pb.TranslateStringIn(key=key, args=args)
class I18nBackend:
def __init__(self, preferred_langs: List[str], ftl_folder: str) -> None:
init_msg = pb.I18nBackendInit(
locale_folder_path=ftl_folder, preferred_langs=preferred_langs
)
self._backend = ankirspy.open_i18n(init_msg.SerializeToString())
def translate(self, key: TR, **kwargs: Union[str, int, float]) -> str:
return self._backend.translate(
translate_string_in(key, **kwargs).SerializeToString()
)
# temporarily force logging of media handling
if "RUST_LOG" not in os.environ:
os.environ["RUST_LOG"] = "warn,anki::media=debug"

View File

@ -17,6 +17,7 @@ import anki.lang
import aqt.buildinfo
from anki import version as _version
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
@ -162,15 +163,15 @@ dialogs = DialogManager()
# 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.
#
# The Qt translator needs to be retained to work.
# A reference to the Qt translator needs to be held to prevent it from
# being immediately deallocated.
_qtrans: Optional[QTranslator] = None
def setupLang(
def setupLangAndBackend(
pm: ProfileManager, app: QApplication, force: Optional[str] = None
) -> None:
) -> RustBackend:
global _qtrans
try:
locale.setlocale(locale.LC_ALL, "")
@ -218,6 +219,8 @@ def setupLang(
if _qtrans.load("qtbase_" + qt_lang, qt_dir):
app.installTranslator(_qtrans)
return anki.lang.current_i18n
# App initialisation
##########################################################################
@ -465,8 +468,8 @@ environment points to a valid, writable folder.""",
if opts.profile:
pm.openProfile(opts.profile)
# i18n
setupLang(pm, app, opts.lang)
# i18n & backend
backend = setupLangAndBackend(pm, app, opts.lang)
if isLin and pm.glMode() == "auto":
from aqt.utils import gfxDriverIsBroken
@ -483,7 +486,7 @@ environment points to a valid, writable folder.""",
# load the main window
import aqt.main
mw = aqt.main.AnkiQt(app, pm, opts, args)
mw = aqt.main.AnkiQt(app, pm, backend, opts, args)
if exec:
app.exec()
else:

View File

@ -29,6 +29,7 @@ from anki import hooks
from anki.collection import _Collection
from anki.hooks import runHook
from anki.lang import _, ngettext
from anki.rsbackend import RustBackend
from anki.sound import AVTag, SoundOrVideoTag
from anki.storage import Collection
from anki.utils import devMode, ids2str, intTime, isMac, isWin, splitFields
@ -78,10 +79,12 @@ class AnkiQt(QMainWindow):
self,
app: QApplication,
profileManager: ProfileManagerType,
backend: RustBackend,
opts: Namespace,
args: List[Any],
) -> None:
QMainWindow.__init__(self)
self.backend = backend
self.state = "startup"
self.opts = opts
self.col: Optional[_Collection] = None

View File

@ -621,52 +621,3 @@ fn media_sync_progress(p: &MediaSyncProgress, i18n: &I18n) -> pb::MediaSyncProgr
),
}
}
/// Standalone I18n backend
/// This is a hack to allow translating strings in the GUI
/// when a collection is not open, and in the future it should
/// either be shared with or merged into the backend object.
///////////////////////////////////////////////////////
pub struct I18nBackend {
i18n: I18n,
}
pub fn init_i18n_backend(init_msg: &[u8]) -> Result<I18nBackend> {
let input: pb::I18nBackendInit = match pb::I18nBackendInit::decode(init_msg) {
Ok(req) => req,
Err(_) => return Err(AnkiError::invalid_input("couldn't decode init msg")),
};
let log = log::terminal();
let i18n = I18n::new(&input.preferred_langs, input.locale_folder_path, log);
Ok(I18nBackend { i18n })
}
impl I18nBackend {
pub fn translate(&self, req: &[u8]) -> String {
let req = match pb::TranslateStringIn::decode(req) {
Ok(req) => req,
Err(_e) => return "decoding error".into(),
};
self.translate_string(req)
}
fn translate_string(&self, input: pb::TranslateStringIn) -> String {
let key = match pb::FluentString::from_i32(input.key) {
Some(key) => key,
None => return "invalid key".to_string(),
};
let map = input
.args
.iter()
.map(|(k, v)| (k.as_str(), translate_arg_to_fluent_val(&v)))
.collect();
self.i18n.trn(key, map)
}
}

View File

@ -1,9 +1,7 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use anki::backend::{
init_backend, init_i18n_backend, Backend as RustBackend, I18nBackend as RustI18nBackend,
};
use anki::backend::{init_backend, Backend as RustBackend};
use pyo3::exceptions::Exception;
use pyo3::prelude::*;
use pyo3::types::PyBytes;
@ -87,30 +85,6 @@ impl Backend {
}
}
// I18n backend
//////////////////////////////////
#[pyclass]
struct I18nBackend {
backend: RustI18nBackend,
}
#[pyfunction]
fn open_i18n(init_msg: &PyBytes) -> PyResult<I18nBackend> {
match init_i18n_backend(init_msg.as_bytes()) {
Ok(backend) => Ok(I18nBackend { backend }),
Err(e) => Err(exceptions::Exception::py_err(format!("{:?}", e))),
}
}
#[pymethods]
impl I18nBackend {
fn translate(&self, input: &PyBytes) -> String {
let in_bytes = input.as_bytes();
self.backend.translate(in_bytes)
}
}
// Module definition
//////////////////////////////////
@ -119,7 +93,6 @@ fn ankirspy(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_class::<Backend>()?;
m.add_wrapped(wrap_pyfunction!(buildhash)).unwrap();
m.add_wrapped(wrap_pyfunction!(open_backend)).unwrap();
m.add_wrapped(wrap_pyfunction!(open_i18n)).unwrap();
Ok(())
}