update 1 arg tr strings in rslib

This commit is contained in:
Damien Elmes 2021-03-27 10:39:53 +10:00
parent d5e5722dc8
commit 698ae855d3
10 changed files with 75 additions and 141 deletions

View file

@ -9,13 +9,20 @@ from re import Match
import stringcase import stringcase
TR_REF = re.compile(r"\.tr\(\s*TR::([^,) ]+)\)") TR_REF = re.compile(r'\.trn\(\s*TR::([^,) ]+),\s+tr_(?:strs|args)!\[((?:"[A-z0-9_]+"\s*=>[^=]+?)+)]\s*,?\s*\)')
TR_ARG_INNER = re.compile(r'"([A-z0-9_]+)"\s*=>(?!=>)+,?\s*')
# eg "count"=>output.trash_count, "megs"=>megs
def rewrite_tr_args(args: str) -> str:
return TR_ARG_INNER.sub("", args)
def repl(m: Match) -> str: def repl(m: Match) -> str:
name = stringcase.snakecase(m.group(1)) name = stringcase.snakecase(m.group(1))
# args = m.group(2) args = rewrite_tr_args(m.group(2))
return f".{name}()" #print(m.group(0))
#print(f".{name}({args})")
#print(args)
return f".{name}({args})"
def update_py(path: str) -> None: def update_py(path: str) -> None:

View file

@ -7,7 +7,7 @@ use inflections::Inflect;
use std::{fmt::Write, fs, path::PathBuf}; use std::{fmt::Write, fs, path::PathBuf};
use crate::{ use crate::{
extract::{Module, Translation, VariableKind}, extract::{Module, Translation},
gather::{TranslationsByFile, TranslationsByLang}, gather::{TranslationsByFile, TranslationsByLang},
}; };
@ -34,6 +34,7 @@ fn write_methods(modules: &[Module], buf: &mut String) {
r#" r#"
use crate::I18n; use crate::I18n;
use crate::tr_args; use crate::tr_args;
use fluent::FluentValue;
use std::borrow::Cow; use std::borrow::Cow;
impl I18n { impl I18n {
@ -46,18 +47,12 @@ impl I18n {
let doc = translation.text.replace("\n", " "); let doc = translation.text.replace("\n", " ");
let in_args; let in_args;
let out_args; let out_args;
let outtype;
let trailer;
if translation.variables.is_empty() { if translation.variables.is_empty() {
in_args = "".to_string(); in_args = "".to_string();
out_args = ", None".to_string(); out_args = ", None".to_string();
outtype = "Cow<'a, str>";
trailer = "";
} else { } else {
in_args = build_in_args(translation); in_args = build_in_args(translation);
out_args = build_out_args(translation); out_args = build_out_args(translation);
outtype = "String";
trailer = ".to_string()";
} }
writeln!( writeln!(
@ -65,16 +60,14 @@ impl I18n {
r#" r#"
/// {doc} /// {doc}
#[inline] #[inline]
pub fn {func}<'a>(&'a self{in_args}) -> {outtype} {{ pub fn {func}<'a>(&'a self{in_args}) -> Cow<'a, str> {{
self.tr_("{key}"{out_args}){trailer} self.tr_("{key}"{out_args})
}}"#, }}"#,
func = func, func = func,
key = key, key = key,
doc = doc, doc = doc,
outtype = outtype,
in_args = in_args, in_args = in_args,
out_args = out_args, out_args = out_args,
trailer = trailer,
) )
.unwrap(); .unwrap();
} }
@ -103,12 +96,13 @@ fn build_in_args(translation: &Translation) -> String {
.variables .variables
.iter() .iter()
.map(|var| { .map(|var| {
let kind = match var.kind { // let kind = match var.kind {
VariableKind::Int => "i64", // VariableKind::Int => "i64",
VariableKind::Float => "f64", // VariableKind::Float => "f64",
VariableKind::String => "&str", // VariableKind::String => "&str",
VariableKind::Any => "&str", // VariableKind::Any => "&str",
}; // };
let kind = "impl Into<FluentValue<'a>>";
format!("{}: {}", var.name.to_snake_case(), kind) format!("{}: {}", var.name.to_snake_case(), kind)
}) })
.collect(); .collect();

View file

@ -57,8 +57,7 @@ pub(super) fn progress_to_proto(progress: Option<Progress>, i18n: &I18n) -> pb::
match progress { match progress {
Progress::MediaSync(p) => pb::progress::Value::MediaSync(media_sync_progress(p, i18n)), Progress::MediaSync(p) => pb::progress::Value::MediaSync(media_sync_progress(p, i18n)),
Progress::MediaCheck(n) => { Progress::MediaCheck(n) => {
let s = i18n.trn(TR::MediaCheckChecked, tr_args!["count"=>n]); pb::progress::Value::MediaCheck(i18n.media_check_checked(n).into())
pb::progress::Value::MediaCheck(s)
} }
Progress::FullSync(p) => pb::progress::Value::FullSync(pb::progress::FullSync { Progress::FullSync(p) => pb::progress::Value::FullSync(pb::progress::FullSync {
transferred: p.transferred_bytes as u32, transferred: p.transferred_bytes as u32,
@ -119,7 +118,7 @@ pub(super) fn progress_to_proto(progress: Option<Progress>, i18n: &I18n) -> pb::
fn media_sync_progress(p: MediaSyncProgress, i18n: &I18n) -> pb::progress::MediaSync { fn media_sync_progress(p: MediaSyncProgress, i18n: &I18n) -> pb::progress::MediaSync {
pb::progress::MediaSync { pb::progress::MediaSync {
checked: i18n.trn(TR::SyncMediaCheckedCount, tr_args!["count"=>p.checked]), checked: i18n.sync_media_checked_count(p.checked).into(),
added: i18n.trn( added: i18n.trn(
TR::SyncMediaAddedCount, TR::SyncMediaAddedCount,
tr_args!["up"=>p.uploaded_files,"down"=>p.downloaded_files], tr_args!["up"=>p.uploaded_files,"down"=>p.downloaded_files],

View file

@ -6,7 +6,7 @@ use std::sync::Arc;
use itertools::Itertools; use itertools::Itertools;
use crate::err::{AnkiError, Result}; use crate::err::{AnkiError, Result};
use crate::i18n::{tr_args, I18n, TR}; use crate::i18n::I18n;
use crate::{ use crate::{
card::{Card, CardID, CardQueue, CardType}, card::{Card, CardID, CardQueue, CardType},
collection::Collection, collection::Collection,
@ -236,12 +236,9 @@ impl<'a> RowContext<'a> {
fn card_due_str(&mut self) -> String { fn card_due_str(&mut self) -> String {
let due = if self.card.original_deck_id != DeckID(0) { let due = if self.card.original_deck_id != DeckID(0) {
self.i18n.browsing_filtered().into() self.i18n.browsing_filtered()
} else if self.card.queue == CardQueue::New || self.card.ctype == CardType::New { } else if self.card.queue == CardQueue::New || self.card.ctype == CardType::New {
self.i18n.trn( self.i18n.statistics_due_for_new_card(self.card.due)
TR::StatisticsDueForNewCard,
tr_args!["number"=>self.card.due],
)
} else { } else {
let date = if self.card.queue == CardQueue::Learn { let date = if self.card.queue == CardQueue::Learn {
TimestampSecs(self.card.due as i64) TimestampSecs(self.card.due as i64)
@ -254,12 +251,12 @@ impl<'a> RowContext<'a> {
} else { } else {
return "".into(); return "".into();
}; };
date.date_string() date.date_string().into()
}; };
if (self.card.queue as i8) < 0 { if (self.card.queue as i8) < 0 {
format!("({})", due) format!("({})", due)
} else { } else {
due due.into()
} }
} }

View file

@ -5,7 +5,7 @@ use crate::{
collection::Collection, collection::Collection,
config::SchedulerVersion, config::SchedulerVersion,
err::{AnkiError, DBErrorKind, Result}, err::{AnkiError, DBErrorKind, Result},
i18n::{tr_args, I18n, TR}, i18n::I18n,
notetype::{ notetype::{
all_stock_notetypes, AlreadyGeneratedCardInfo, CardGenContext, NoteType, NoteTypeID, all_stock_notetypes, AlreadyGeneratedCardInfo, CardGenContext, NoteType, NoteTypeID,
NoteTypeKind, NoteTypeKind,
@ -45,68 +45,38 @@ impl CheckDatabaseOutput {
let mut probs = Vec::new(); let mut probs = Vec::new();
if self.notetypes_recovered > 0 { if self.notetypes_recovered > 0 {
probs.push(i18n.trn( probs.push(i18n.database_check_notetypes_recovered());
TR::DatabaseCheckNotetypesRecovered,
tr_args!["count"=>self.revlog_properties_invalid],
));
} }
if self.card_position_too_high > 0 { if self.card_position_too_high > 0 {
probs.push(i18n.trn( probs.push(i18n.database_check_new_card_high_due(self.card_position_too_high));
TR::DatabaseCheckNewCardHighDue,
tr_args!["count"=>self.card_position_too_high],
));
} }
if self.card_properties_invalid > 0 { if self.card_properties_invalid > 0 {
probs.push(i18n.trn( probs.push(i18n.database_check_card_properties(self.card_properties_invalid));
TR::DatabaseCheckCardProperties,
tr_args!["count"=>self.card_properties_invalid],
));
} }
if self.cards_missing_note > 0 { if self.cards_missing_note > 0 {
probs.push(i18n.trn( probs.push(i18n.database_check_card_missing_note(self.cards_missing_note));
TR::DatabaseCheckCardMissingNote,
tr_args!["count"=>self.cards_missing_note],
));
} }
if self.decks_missing > 0 { if self.decks_missing > 0 {
probs.push(i18n.trn( probs.push(i18n.database_check_missing_decks(self.decks_missing));
TR::DatabaseCheckMissingDecks,
tr_args!["count"=>self.decks_missing],
));
} }
if self.field_count_mismatch > 0 { if self.field_count_mismatch > 0 {
probs.push(i18n.trn( probs.push(i18n.database_check_field_count(self.field_count_mismatch));
TR::DatabaseCheckFieldCount,
tr_args!["count"=>self.field_count_mismatch],
));
} }
if self.card_ords_duplicated > 0 { if self.card_ords_duplicated > 0 {
probs.push(i18n.trn( probs.push(i18n.database_check_duplicate_card_ords(self.card_ords_duplicated));
TR::DatabaseCheckDuplicateCardOrds,
tr_args!["count"=>self.card_ords_duplicated],
));
} }
if self.templates_missing > 0 { if self.templates_missing > 0 {
probs.push(i18n.trn( probs.push(i18n.database_check_missing_templates(self.templates_missing));
TR::DatabaseCheckMissingTemplates,
tr_args!["count"=>self.templates_missing],
));
} }
if self.revlog_properties_invalid > 0 { if self.revlog_properties_invalid > 0 {
probs.push(i18n.trn( probs.push(i18n.database_check_revlog_properties(self.revlog_properties_invalid));
TR::DatabaseCheckRevlogProperties,
tr_args!["count"=>self.revlog_properties_invalid],
));
} }
if self.invalid_utf8 > 0 { if self.invalid_utf8 > 0 {
probs.push(i18n.trn( probs.push(i18n.database_check_notes_with_invalid_utf8(self.invalid_utf8));
TR::DatabaseCheckNotesWithInvalidUtf8,
tr_args!["count"=>self.invalid_utf8],
));
} }
probs probs.into_iter().map(Into::into).collect()
} }
} }

View file

@ -1,7 +1,7 @@
// Copyright: Ankitects Pty Ltd and contributors // Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use crate::i18n::{tr_args, tr_strs, I18n, TR}; use crate::i18n::I18n;
pub use failure::{Error, Fail}; pub use failure::{Error, Fail};
use nom::error::{ErrorKind as NomErrorKind, ParseError as NomParseError}; use nom::error::{ErrorKind as NomErrorKind, ParseError as NomParseError};
use reqwest::StatusCode; use reqwest::StatusCode;
@ -113,17 +113,16 @@ impl AnkiError {
NetworkErrorKind::ProxyAuth => i18n.network_proxy_auth(), NetworkErrorKind::ProxyAuth => i18n.network_proxy_auth(),
NetworkErrorKind::Other => i18n.network_other(), NetworkErrorKind::Other => i18n.network_other(),
}; };
let details = i18n.trn(TR::NetworkDetails, tr_strs!["details"=>info]); let details = i18n.network_details(info.as_str());
format!("{}\n\n{}", summary, details) format!("{}\n\n{}", summary, details)
} }
AnkiError::TemplateError { info } => { AnkiError::TemplateError { info } => {
// already localized // already localized
info.into() info.into()
} }
AnkiError::TemplateSaveError { ordinal } => i18n.trn( AnkiError::TemplateSaveError { ordinal } => i18n
TR::CardTemplatesInvalidTemplateNumber, .card_templates_invalid_template_number(ordinal + 1)
tr_args!["number"=>ordinal+1], .into(),
),
AnkiError::DBError { info, kind } => match kind { AnkiError::DBError { info, kind } => match kind {
DBErrorKind::Corrupt => info.clone(), DBErrorKind::Corrupt => info.clone(),
DBErrorKind::Locked => "Anki already open, or media currently syncing.".into(), DBErrorKind::Locked => "Anki already open, or media currently syncing.".into(),
@ -139,12 +138,9 @@ impl AnkiError {
SearchErrorKind::EmptyQuote => i18n.search_empty_quote(), SearchErrorKind::EmptyQuote => i18n.search_empty_quote(),
SearchErrorKind::UnclosedQuote => i18n.search_unclosed_quote(), SearchErrorKind::UnclosedQuote => i18n.search_unclosed_quote(),
SearchErrorKind::MissingKey => i18n.search_missing_key(), SearchErrorKind::MissingKey => i18n.search_missing_key(),
SearchErrorKind::UnknownEscape(ctx) => i18n SearchErrorKind::UnknownEscape(ctx) => {
.trn( i18n.search_unknown_escape(ctx.replace('`', "'")).into()
TR::SearchUnknownEscape, }
tr_strs!["val"=>(ctx.replace('`', "'"))],
)
.into(),
SearchErrorKind::InvalidState(state) => i18n SearchErrorKind::InvalidState(state) => i18n
.trn( .trn(
TR::SearchInvalidArgument, TR::SearchInvalidArgument,
@ -158,10 +154,12 @@ impl AnkiError {
tr_strs!("term" => "prop:", "argument" => prop.replace('`', "'")), tr_strs!("term" => "prop:", "argument" => prop.replace('`', "'")),
) )
.into(), .into(),
SearchErrorKind::InvalidPropOperator(ctx) => i18n SearchErrorKind::InvalidPropOperator(ctx) => {
.trn(TR::SearchInvalidPropOperator, tr_strs!["val"=>(ctx)]) i18n.search_invalid_prop_operator(ctx.as_str()).into()
.into(), }
SearchErrorKind::Regex(text) => format!("<pre>`{}`</pre>", text.replace('`', "'")).into(), SearchErrorKind::Regex(text) => {
format!("<pre>`{}`</pre>", text.replace('`', "'")).into()
}
SearchErrorKind::Other(Some(info)) => info.into(), SearchErrorKind::Other(Some(info)) => info.into(),
SearchErrorKind::Other(None) => i18n.search_invalid_other(), SearchErrorKind::Other(None) => i18n.search_invalid_other(),
SearchErrorKind::InvalidNumber { provided, context } => i18n SearchErrorKind::InvalidNumber { provided, context } => i18n
@ -195,19 +193,13 @@ impl AnkiError {
) )
.into(), .into(),
}; };
i18n.trn( i18n.search_invalid_search(reason).into()
TR::SearchInvalidSearch,
tr_args!("reason" => reason.into_owned()),
)
} }
AnkiError::InvalidInput { info } => { AnkiError::InvalidInput { info } => {
if info.is_empty() { if info.is_empty() {
i18n.errors_invalid_input_empty().into() i18n.errors_invalid_input_empty().into()
} else { } else {
i18n.trn( i18n.errors_invalid_input_details(info.as_str()).into()
TR::ErrorsInvalidInputDetails,
tr_args!("details" => info.to_owned()),
)
} }
} }
AnkiError::ParseNumError => i18n.errors_parse_number_fail().into(), AnkiError::ParseNumError => i18n.errors_parse_number_fail().into(),

View file

@ -3,7 +3,6 @@
use crate::collection::Collection; use crate::collection::Collection;
use crate::err::{AnkiError, DBErrorKind, Result}; use crate::err::{AnkiError, DBErrorKind, Result};
use crate::i18n::{tr_args, tr_strs, TR};
use crate::latex::extract_latex_expanding_clozes; use crate::latex::extract_latex_expanding_clozes;
use crate::log::debug; use crate::log::debug;
use crate::media::database::MediaDatabaseContext; use crate::media::database::MediaDatabaseContext;
@ -102,37 +101,22 @@ where
buf.push('\n'); buf.push('\n');
} }
buf += &i.trn( buf += &i.media_check_missing_count(output.missing.len());
TR::MediaCheckMissingCount,
tr_args!["count"=>output.missing.len()],
);
buf.push('\n'); buf.push('\n');
buf += &i.trn( buf += &i.media_check_unused_count(output.unused.len());
TR::MediaCheckUnusedCount,
tr_args!["count"=>output.unused.len()],
);
buf.push('\n'); buf.push('\n');
if !output.renamed.is_empty() { if !output.renamed.is_empty() {
buf += &i.trn( buf += &i.media_check_renamed_count(output.renamed.len());
TR::MediaCheckRenamedCount,
tr_args!["count"=>output.renamed.len()],
);
buf.push('\n'); buf.push('\n');
} }
if !output.oversize.is_empty() { if !output.oversize.is_empty() {
buf += &i.trn( buf += &i.media_check_oversize_count(output.oversize.len());
TR::MediaCheckOversizeCount,
tr_args!["count"=>output.oversize.len()],
);
buf.push('\n'); buf.push('\n');
} }
if !output.dirs.is_empty() { if !output.dirs.is_empty() {
buf += &i.trn( buf += &i.media_check_subfolder_count(output.dirs.len());
TR::MediaCheckSubfolderCount,
tr_args!["count"=>output.dirs.len()],
);
buf.push('\n'); buf.push('\n');
} }
@ -153,7 +137,7 @@ where
buf += &i.media_check_oversize_header(); buf += &i.media_check_oversize_header();
buf.push('\n'); buf.push('\n');
for fname in &output.oversize { for fname in &output.oversize {
buf += &i.trn(TR::MediaCheckOversizeFile, tr_strs!["filename"=>fname]); buf += &i.media_check_oversize_file(fname.as_str());
buf.push('\n'); buf.push('\n');
} }
buf.push('\n') buf.push('\n')
@ -164,7 +148,7 @@ where
buf += &i.media_check_subfolder_header(); buf += &i.media_check_subfolder_header();
buf.push('\n'); buf.push('\n');
for fname in &output.dirs { for fname in &output.dirs {
buf += &i.trn(TR::MediaCheckSubfolderFile, tr_strs!["filename"=>fname]); buf += &i.media_check_subfolder_file(fname.as_str());
buf.push('\n'); buf.push('\n');
} }
buf.push('\n') buf.push('\n')
@ -175,7 +159,7 @@ where
buf += &i.media_check_missing_header(); buf += &i.media_check_missing_header();
buf.push('\n'); buf.push('\n');
for fname in &output.missing { for fname in &output.missing {
buf += &i.trn(TR::MediaCheckMissingFile, tr_strs!["filename"=>fname]); buf += &i.media_check_missing_file(fname.as_str());
buf.push('\n'); buf.push('\n');
} }
buf.push('\n') buf.push('\n')
@ -186,7 +170,7 @@ where
buf += &i.media_check_unused_header(); buf += &i.media_check_unused_header();
buf.push('\n'); buf.push('\n');
for fname in &output.unused { for fname in &output.unused {
buf += &i.trn(TR::MediaCheckUnusedFile, tr_strs!["filename"=>fname]); buf += &i.media_check_unused_file(fname.as_str());
buf.push('\n'); buf.push('\n');
} }
} }

View file

@ -79,10 +79,7 @@ impl Collection {
write!( write!(
buf, buf,
"<div><b>{}</b></div><ol>", "<div><b>{}</b></div><ol>",
self.i18n.trn( self.i18n.empty_cards_for_note_type(nt.name.clone())
TR::EmptyCardsForNoteType,
tr_args!["notetype"=>nt.name.clone()],
)
) )
.unwrap(); .unwrap();

View file

@ -241,10 +241,9 @@ fn revlog_to_text(e: RevlogEntry, i18n: &I18n) -> RevlogText {
} else { } else {
"".to_string() "".to_string()
}; };
let taken_secs = i18n.trn( let taken_secs = i18n
TR::StatisticsSecondsTaken, .statistics_seconds_taken((e.taken_millis / 1000) as i32)
tr_args!["seconds"=>(e.taken_millis / 1000) as i32], .into();
);
RevlogText { RevlogText {
time, time,

View file

@ -2,7 +2,7 @@
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use crate::err::{AnkiError, Result, TemplateError}; use crate::err::{AnkiError, Result, TemplateError};
use crate::i18n::{tr_args, tr_strs, I18n, TR}; use crate::i18n::{tr_strs, I18n, TR};
use crate::{cloze::add_cloze_numbers_in_string, template_filters::apply_filters}; use crate::{cloze::add_cloze_numbers_in_string, template_filters::apply_filters};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use nom::branch::alt; use nom::branch::alt;
@ -267,11 +267,9 @@ fn localized_template_error(i18n: &I18n, err: TemplateError) -> String {
TemplateError::NoClosingBrackets(tag) => i18n.trn( TemplateError::NoClosingBrackets(tag) => i18n.trn(
TR::CardTemplateRenderingNoClosingBrackets, TR::CardTemplateRenderingNoClosingBrackets,
tr_strs!("tag"=>tag, "missing"=>"}}"), tr_strs!("tag"=>tag, "missing"=>"}}"),
), TemplateError::ConditionalNotClosed(tag) => i18n
TemplateError::ConditionalNotClosed(tag) => i18n.trn( .card_template_rendering_conditional_not_closed(format!("{{{{/{}}}}}", tag))
TR::CardTemplateRenderingConditionalNotClosed, .into(),
tr_strs!("missing"=>format!("{{{{/{}}}}}", tag)),
),
TemplateError::ConditionalNotOpen { TemplateError::ConditionalNotOpen {
closed, closed,
currently_open, currently_open,
@ -561,10 +559,7 @@ pub fn render_card(
let empty_message = if is_cloze && cloze_is_empty(field_map, card_ord) { let empty_message = if is_cloze && cloze_is_empty(field_map, card_ord) {
Some(format!( Some(format!(
"<div>{}<br><a href='{}'>{}</a></div>", "<div>{}<br><a href='{}'>{}</a></div>",
i18n.trn( i18n.card_template_rendering_missing_cloze(card_ord + 1),
TR::CardTemplateRenderingMissingCloze,
tr_args!["number"=>card_ord+1]
),
TEMPLATE_BLANK_CLOZE_LINK, TEMPLATE_BLANK_CLOZE_LINK,
i18n.card_template_rendering_more_info() i18n.card_template_rendering_more_info()
)) ))