expose translations to Python

This commit is contained in:
Damien Elmes 2020-02-16 21:07:40 +10:00
parent 4fe47b7be4
commit c395003def
4 changed files with 76 additions and 1 deletions

View file

@ -39,6 +39,7 @@ message BackendInput {
SyncMediaIn sync_media = 27;
Empty check_media = 28;
TrashMediaFilesIn trash_media_files = 29;
TranslateStringIn translate_string = 30;
}
}
@ -58,6 +59,7 @@ message BackendOutput {
Empty sync_media = 27;
MediaCheckOut check_media = 28;
Empty trash_media_files = 29;
string translate_string = 30;
BackendError error = 2047;
}
@ -281,4 +283,17 @@ message MediaCheckOut {
message TrashMediaFilesIn {
repeated string fnames = 1;
}
}
message TranslateStringIn {
StringsGroup group = 1;
string key = 2;
map<string,TranslateArgValue> args = 3;
}
message TranslateArgValue {
oneof value {
string str = 1;
string number = 2;
}
}

View file

@ -126,6 +126,8 @@ MediaSyncProgress = pb.MediaSyncProgress
MediaCheckOutput = pb.MediaCheckOut
StringsGroup = pb.StringsGroup
@dataclass
class ExtractedLatex:
@ -318,3 +320,19 @@ class RustBackend:
self._run_command(
pb.BackendInput(trash_media_files=pb.TrashMediaFilesIn(fnames=fnames))
)
def translate(
self, group: pb.StringsGroup, key: str, **kwargs: Union[str, int, float]
):
args = {}
for (k, v) in kwargs.items():
if isinstance(v, str):
args[k] = pb.TranslateArgValue(str=v)
else:
args[k] = pb.TranslateArgValue(number=str(v))
return self._run_command(
pb.BackendInput(
translate_string=pb.TranslateStringIn(group=group, key=key, args=args)
)
).translate_string

View file

@ -4,6 +4,7 @@ import os
import tempfile
from anki import Collection as aopen
from anki.rsbackend import StringsGroup
from anki.stdmodels import addBasicModel, models
from anki.utils import isWin
from tests.shared import assertException, getEmptyCol
@ -147,3 +148,17 @@ def test_furigana():
m["tmpls"][0]["qfmt"] = "{{kana:}}"
mm.save(m)
c.q(reload=True)
def test_translate():
d = getEmptyCol()
tr = d.backend.translate
# strip off unicode separators
def no_uni(s: str) -> str:
return s.replace("\u2068", "").replace("\u2069", "")
assert tr(StringsGroup.TEST, "valid-key") == "a valid key"
assert "invalid-key" in tr(StringsGroup.TEST, "invalid-key")
assert no_uni(tr(StringsGroup.TEST, "plural", hats=1)) == "You have 1 hat."
assert no_uni(tr(StringsGroup.TEST, "plural", hats=2)) == "You have 2 hats."

View file

@ -16,6 +16,7 @@ use crate::template::{
RenderedNode,
};
use crate::text::{extract_av_tags, strip_av_tags, AVTag};
use fluent::FluentValue;
use prost::Message;
use std::collections::{HashMap, HashSet};
use std::path::PathBuf;
@ -193,6 +194,7 @@ impl Backend {
self.remove_media_files(&input.fnames)?;
OValue::TrashMediaFiles(Empty {})
}
Value::TranslateString(input) => OValue::TranslateString(self.translate_string(input)),
})
}
@ -376,6 +378,31 @@ impl Backend {
let mut ctx = mgr.dbctx();
mgr.remove_files(&mut ctx, fnames)
}
fn translate_string(&self, input: pb::TranslateStringIn) -> String {
let group = match pb::StringsGroup::from_i32(input.group) {
Some(group) => group,
None => return "".to_string(),
};
let map = input
.args
.iter()
.map(|(k, v)| (k.as_str(), translate_arg_to_fluent_val(&v)))
.collect();
self.i18n.get(group).trn(&input.key, map)
}
}
fn translate_arg_to_fluent_val(arg: &pb::TranslateArgValue) -> FluentValue {
use pb::translate_arg_value::Value as V;
match &arg.value {
Some(val) => match val {
V::Str(s) => FluentValue::String(s.into()),
V::Number(s) => FluentValue::Number(s.into()),
},
None => FluentValue::String("".into()),
}
}
fn ords_hash_to_set(ords: HashSet<u16>) -> Vec<u32> {