mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 16:56:36 -04:00
expose translations to Python
This commit is contained in:
parent
4fe47b7be4
commit
c395003def
4 changed files with 76 additions and 1 deletions
|
@ -39,6 +39,7 @@ message BackendInput {
|
||||||
SyncMediaIn sync_media = 27;
|
SyncMediaIn sync_media = 27;
|
||||||
Empty check_media = 28;
|
Empty check_media = 28;
|
||||||
TrashMediaFilesIn trash_media_files = 29;
|
TrashMediaFilesIn trash_media_files = 29;
|
||||||
|
TranslateStringIn translate_string = 30;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +59,7 @@ message BackendOutput {
|
||||||
Empty sync_media = 27;
|
Empty sync_media = 27;
|
||||||
MediaCheckOut check_media = 28;
|
MediaCheckOut check_media = 28;
|
||||||
Empty trash_media_files = 29;
|
Empty trash_media_files = 29;
|
||||||
|
string translate_string = 30;
|
||||||
|
|
||||||
BackendError error = 2047;
|
BackendError error = 2047;
|
||||||
}
|
}
|
||||||
|
@ -281,4 +283,17 @@ message MediaCheckOut {
|
||||||
|
|
||||||
message TrashMediaFilesIn {
|
message TrashMediaFilesIn {
|
||||||
repeated string fnames = 1;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -126,6 +126,8 @@ MediaSyncProgress = pb.MediaSyncProgress
|
||||||
|
|
||||||
MediaCheckOutput = pb.MediaCheckOut
|
MediaCheckOutput = pb.MediaCheckOut
|
||||||
|
|
||||||
|
StringsGroup = pb.StringsGroup
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class ExtractedLatex:
|
class ExtractedLatex:
|
||||||
|
@ -318,3 +320,19 @@ class RustBackend:
|
||||||
self._run_command(
|
self._run_command(
|
||||||
pb.BackendInput(trash_media_files=pb.TrashMediaFilesIn(fnames=fnames))
|
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
|
||||||
|
|
|
@ -4,6 +4,7 @@ import os
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
from anki import Collection as aopen
|
from anki import Collection as aopen
|
||||||
|
from anki.rsbackend import StringsGroup
|
||||||
from anki.stdmodels import addBasicModel, models
|
from anki.stdmodels import addBasicModel, models
|
||||||
from anki.utils import isWin
|
from anki.utils import isWin
|
||||||
from tests.shared import assertException, getEmptyCol
|
from tests.shared import assertException, getEmptyCol
|
||||||
|
@ -147,3 +148,17 @@ def test_furigana():
|
||||||
m["tmpls"][0]["qfmt"] = "{{kana:}}"
|
m["tmpls"][0]["qfmt"] = "{{kana:}}"
|
||||||
mm.save(m)
|
mm.save(m)
|
||||||
c.q(reload=True)
|
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."
|
||||||
|
|
|
@ -16,6 +16,7 @@ use crate::template::{
|
||||||
RenderedNode,
|
RenderedNode,
|
||||||
};
|
};
|
||||||
use crate::text::{extract_av_tags, strip_av_tags, AVTag};
|
use crate::text::{extract_av_tags, strip_av_tags, AVTag};
|
||||||
|
use fluent::FluentValue;
|
||||||
use prost::Message;
|
use prost::Message;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -193,6 +194,7 @@ impl Backend {
|
||||||
self.remove_media_files(&input.fnames)?;
|
self.remove_media_files(&input.fnames)?;
|
||||||
OValue::TrashMediaFiles(Empty {})
|
OValue::TrashMediaFiles(Empty {})
|
||||||
}
|
}
|
||||||
|
Value::TranslateString(input) => OValue::TranslateString(self.translate_string(input)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,6 +378,31 @@ impl Backend {
|
||||||
let mut ctx = mgr.dbctx();
|
let mut ctx = mgr.dbctx();
|
||||||
mgr.remove_files(&mut ctx, fnames)
|
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> {
|
fn ords_hash_to_set(ords: HashSet<u16>) -> Vec<u32> {
|
||||||
|
|
Loading…
Reference in a new issue