allow js to request specific i18n modules
Brings the payload on the congrats page with a non-English language down from about 150k to 15k
This commit is contained in:
parent
8920a6f9ea
commit
b57e9be46f
@ -1041,8 +1041,8 @@ table.review-log {{ {revlog_style} }}
|
||||
def set_wants_abort(self) -> None:
|
||||
self._backend.set_wants_abort()
|
||||
|
||||
def i18n_resources(self) -> bytes:
|
||||
return self._backend.i18n_resources()
|
||||
def i18n_resources(self, modules: Sequence[str]) -> bytes:
|
||||
return self._backend.i18n_resources(modules=modules)
|
||||
|
||||
def abort_media_sync(self) -> None:
|
||||
self._backend.abort_media_sync()
|
||||
|
@ -269,12 +269,17 @@ def congrats_info() -> bytes:
|
||||
return aqt.mw.col.congrats_info()
|
||||
|
||||
|
||||
def i18n_resources() -> bytes:
|
||||
args = from_json_bytes(request.data)
|
||||
return aqt.mw.col.i18n_resources(modules=args["modules"])
|
||||
|
||||
|
||||
post_handlers = {
|
||||
"graphData": graph_data,
|
||||
"graphPreferences": graph_preferences,
|
||||
"setGraphPreferences": set_graph_preferences,
|
||||
# pylint: disable=unnecessary-lambda
|
||||
"i18nResources": lambda: aqt.mw.col.i18n_resources(),
|
||||
"i18nResources": i18n_resources,
|
||||
"congratsInfo": congrats_info,
|
||||
}
|
||||
|
||||
|
@ -263,7 +263,7 @@ service MediaService {
|
||||
service I18nService {
|
||||
rpc TranslateString(TranslateStringIn) returns (String);
|
||||
rpc FormatTimespan(FormatTimespanIn) returns (String);
|
||||
rpc I18nResources(Empty) returns (Json);
|
||||
rpc I18nResources(I18nResourcesIn) returns (Json);
|
||||
}
|
||||
|
||||
service CollectionService {
|
||||
@ -773,6 +773,10 @@ message FormatTimespanIn {
|
||||
Context context = 2;
|
||||
}
|
||||
|
||||
message I18nResourcesIn {
|
||||
repeated string modules = 1;
|
||||
}
|
||||
|
||||
message StudiedTodayMessageIn {
|
||||
uint32 cards = 1;
|
||||
double seconds = 2;
|
||||
|
@ -183,7 +183,6 @@ impl I18n {
|
||||
pub fn new<S: AsRef<str>>(locale_codes: &[S]) -> Self {
|
||||
let mut input_langs = vec![];
|
||||
let mut bundles = Vec::with_capacity(locale_codes.len() + 1);
|
||||
let mut resource_text = vec![];
|
||||
|
||||
for code in locale_codes {
|
||||
let code = code.as_ref();
|
||||
@ -210,7 +209,6 @@ impl I18n {
|
||||
}
|
||||
}) {
|
||||
if let Some(bundle) = get_bundle_with_extra(&text, Some(lang.clone())) {
|
||||
resource_text.push(text);
|
||||
bundles.push(bundle);
|
||||
output_langs.push(lang);
|
||||
} else {
|
||||
@ -223,7 +221,6 @@ impl I18n {
|
||||
let template_lang = "en-US".parse().unwrap();
|
||||
let template_text = ftl_localized_text(&template_lang).unwrap();
|
||||
let template_bundle = get_bundle_with_extra(&template_text, None).unwrap();
|
||||
resource_text.push(template_text);
|
||||
bundles.push(template_bundle);
|
||||
output_langs.push(template_lang);
|
||||
|
||||
@ -238,7 +235,6 @@ impl I18n {
|
||||
inner: Arc::new(Mutex::new(I18nInner {
|
||||
bundles,
|
||||
langs: output_langs,
|
||||
resource_text,
|
||||
})),
|
||||
}
|
||||
}
|
||||
@ -288,15 +284,35 @@ impl I18n {
|
||||
}
|
||||
|
||||
/// Return text from configured locales for use with the JS Fluent implementation.
|
||||
pub fn resources_for_js(&self) -> ResourcesForJavascript {
|
||||
pub fn resources_for_js(&self, desired_modules: &[String]) -> ResourcesForJavascript {
|
||||
let inner = self.inner.lock().unwrap();
|
||||
let resources = get_modules(&inner.langs, desired_modules);
|
||||
ResourcesForJavascript {
|
||||
langs: inner.langs.iter().map(ToString::to_string).collect(),
|
||||
resources: inner.resource_text.clone(),
|
||||
resources,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_modules(langs: &[LanguageIdentifier], desired_modules: &[String]) -> Vec<String> {
|
||||
langs
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|lang| {
|
||||
let mut buf = String::new();
|
||||
let lang_name = remapped_lang_name(&lang);
|
||||
if let Some(strings) = STRINGS.get(lang_name) {
|
||||
for module_name in desired_modules {
|
||||
if let Some(text) = strings.get(module_name.as_str()) {
|
||||
buf.push_str(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
buf
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// This temporarily behaves like the older code; in the future we could either
|
||||
/// access each &str separately, or load them on demand.
|
||||
fn ftl_localized_text(lang: &LanguageIdentifier) -> Option<String> {
|
||||
@ -317,9 +333,6 @@ struct I18nInner {
|
||||
// last element
|
||||
bundles: Vec<FluentBundle<FluentResource>>,
|
||||
langs: Vec<LanguageIdentifier>,
|
||||
// fixme: this is a relic from the old implementation, and we could gather
|
||||
// it only when needed in the future
|
||||
resource_text: Vec<String>,
|
||||
}
|
||||
|
||||
// Simple number formatting implementation
|
||||
|
@ -32,8 +32,8 @@ impl I18nService for Backend {
|
||||
.into())
|
||||
}
|
||||
|
||||
fn i18n_resources(&self, _input: pb::Empty) -> Result<pb::Json> {
|
||||
serde_json::to_vec(&self.i18n.resources_for_js())
|
||||
fn i18n_resources(&self, input: pb::I18nResourcesIn) -> Result<pb::Json> {
|
||||
serde_json::to_vec(&self.i18n.resources_for_js(&input.modules))
|
||||
.map(Into::into)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
@ -2,14 +2,14 @@
|
||||
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||
|
||||
import { getCongratsInfo } from "./lib";
|
||||
import { setupI18n } from "anki/i18n";
|
||||
import { setupI18n, ModuleName } from "anki/i18n";
|
||||
import { checkNightMode } from "anki/nightmode";
|
||||
|
||||
import CongratsPage from "./CongratsPage.svelte";
|
||||
|
||||
export async function congrats(target: HTMLDivElement): Promise<void> {
|
||||
checkNightMode();
|
||||
await setupI18n();
|
||||
await setupI18n({ modules: [ModuleName.SCHEDULING] });
|
||||
const info = await getCongratsInfo();
|
||||
new CongratsPage({
|
||||
target,
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
import type { SvelteComponent } from "svelte/internal";
|
||||
|
||||
import { setupI18n } from "anki/i18n";
|
||||
import { setupI18n, ModuleName } from "anki/i18n";
|
||||
import { checkNightMode } from "anki/nightmode";
|
||||
|
||||
import GraphsPage from "./GraphsPage.svelte";
|
||||
@ -33,7 +33,7 @@ export function graphs(
|
||||
): void {
|
||||
const nightMode = checkNightMode();
|
||||
|
||||
setupI18n().then(() => {
|
||||
setupI18n({ modules: [ModuleName.STATISTICS, ModuleName.SCHEDULING] }).then(() => {
|
||||
new GraphsPage({
|
||||
target,
|
||||
props: {
|
||||
|
@ -91,11 +91,20 @@ def typescript_arg_name(arg: Variable) -> str:
|
||||
else:
|
||||
return name
|
||||
|
||||
def module_names() -> str:
|
||||
buf = "export enum ModuleName {\n"
|
||||
for module in modules:
|
||||
name = module["name"]
|
||||
upper = name.upper()
|
||||
buf += f' {upper} = "{name}",\n'
|
||||
buf += "}\n"
|
||||
return buf
|
||||
|
||||
|
||||
out = ""
|
||||
|
||||
out += methods()
|
||||
|
||||
out += module_names()
|
||||
|
||||
open(outfile, "wb").write(
|
||||
(
|
||||
|
@ -70,8 +70,13 @@ export class I18n {
|
||||
// global singleton
|
||||
export const i18n = new I18n();
|
||||
|
||||
export async function setupI18n(): Promise<void> {
|
||||
const resp = await fetch("/_anki/i18nResources", { method: "POST" });
|
||||
import type { ModuleName } from "./i18n";
|
||||
|
||||
export async function setupI18n(args: { modules: ModuleName[] }): Promise<void> {
|
||||
const resp = await fetch("/_anki/i18nResources", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(args),
|
||||
});
|
||||
if (!resp.ok) {
|
||||
throw Error(`unexpected reply: ${resp.statusText}`);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user