update remaining TR references in rslib

This commit is contained in:
Damien Elmes 2021-03-27 11:07:36 +10:00
parent c45ab78b73
commit f485efce16
8 changed files with 111 additions and 133 deletions

View File

@ -9,19 +9,22 @@ from re import Match
import stringcase
TR_REF = re.compile(r'\.trn\(\s*TR::([^,) ]+),\s+tr_(?:strs|args)!\[((?:"[A-z0-9_]+"\s*=>[^=]+?)+)]\s*,?\s*\)')
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:
name = stringcase.snakecase(m.group(1))
args = rewrite_tr_args(m.group(2))
#print(m.group(0))
#print(f".{name}({args})")
#print(args)
# print(m.group(0))
# print(f".{name}({args})")
# print(args)
return f".{name}({args})"

View File

@ -7,7 +7,7 @@ use std::sync::{Arc, Mutex};
use crate::{
backend_proto as pb,
dbcheck::DatabaseCheckProgress,
i18n::{tr_args, I18n, TR},
i18n::I18n,
media::sync::MediaSyncProgress,
sync::{FullSyncProgress, NormalSyncProgress, SyncStage},
};
@ -70,16 +70,12 @@ pub(super) fn progress_to_proto(progress: Option<Progress>, i18n: &I18n) -> pb::
SyncStage::Finalizing => i18n.sync_checking(),
}
.to_string();
let added = i18n.trn(
TR::SyncAddedUpdatedCount,
tr_args![
"up"=>p.local_update, "down"=>p.remote_update],
);
let removed = i18n.trn(
TR::SyncMediaRemovedCount,
tr_args![
"up"=>p.local_remove, "down"=>p.remote_remove],
);
let added = i18n
.sync_added_updated_count(p.local_update, p.remote_update)
.into();
let removed = i18n
.sync_media_removed_count(p.local_remove, p.remote_remove)
.into();
pb::progress::Value::NormalSync(pb::progress::NormalSync {
stage,
added,

View File

@ -139,17 +139,18 @@ impl AnkiError {
SearchErrorKind::UnclosedQuote => i18n.search_unclosed_quote(),
SearchErrorKind::MissingKey => i18n.search_missing_key(),
SearchErrorKind::UnknownEscape(ctx) => {
i18n.search_unknown_escape(ctx.replace('`', "'")).into()
i18n.search_unknown_escape(ctx.replace('`', "'"))
}
SearchErrorKind::InvalidState(state) => i18n
.search_invalid_argument("is:", state.replace('`', "'"))
.into(),
SearchErrorKind::InvalidState(state) => {
i18n.search_invalid_argument("is:", state.replace('`', "'"))
}
SearchErrorKind::InvalidFlag => i18n.search_invalid_flag(),
SearchErrorKind::InvalidPropProperty(prop) => i18n
.search_invalid_argument("prop:", prop.replace('`', "'"))
.into(),
SearchErrorKind::InvalidPropProperty(prop) => {
i18n.search_invalid_argument("prop:", prop.replace('`', "'"))
}
SearchErrorKind::InvalidPropOperator(ctx) => {
i18n.search_invalid_prop_operator(ctx.as_str()).into()
i18n.search_invalid_prop_operator(ctx.as_str())
}
SearchErrorKind::Regex(text) => {
format!("<pre>`{}`</pre>", text.replace('`', "'")).into()
@ -160,32 +161,31 @@ impl AnkiError {
.search_invalid_number(
context.replace('`', "'"),
provided.replace('`', "'"),
)
.into(),
),
SearchErrorKind::InvalidWholeNumber { provided, context } => i18n
.search_invalid_whole_number(
context.replace('`', "'"),
provided.replace('`', "'"),
)
.into(),
),
SearchErrorKind::InvalidPositiveWholeNumber { provided, context } => i18n
.search_invalid_positive_whole_number(
context.replace('`', "'"),
provided.replace('`', "'"),
)
.into(),
),
SearchErrorKind::InvalidNegativeWholeNumber { provided, context } => i18n
.search_invalid_negative_whole_number(
context.replace('`', "'"),
provided.replace('`', "'"),
)
.into(),
),
SearchErrorKind::InvalidAnswerButton { provided, context } => i18n
.search_invalid_answer_button(
context.replace('`', "'"),
provided.replace('`', "'"),
)
.into(),
),
};
i18n.search_invalid_search(reason).into()
}

View File

@ -4,13 +4,7 @@
use super::{
cardgen::group_generated_cards_by_note, CardGenContext, NoteType, NoteTypeID, NoteTypeKind,
};
use crate::{
card::CardID,
collection::Collection,
err::Result,
i18n::{tr_args, TR},
notes::NoteID,
};
use crate::{card::CardID, collection::Collection, err::Result, notes::NoteID};
use std::collections::HashSet;
use std::fmt::Write;
@ -119,13 +113,10 @@ impl Collection {
"<li class={}>[anki:nid:{}] {}</li>",
class,
note.nid,
self.i18n.trn(
TR::EmptyCardsCountLine,
tr_args![
"empty_count"=>note.empty.len(),
"existing_count"=>note.current_count,
"template_names"=>templates
],
self.i18n.empty_cards_count_line(
note.empty.len(),
note.current_count,
templates
)
)
.unwrap();

View File

@ -37,38 +37,37 @@ pub enum Op {
impl Op {
pub fn describe(self, i18n: &I18n) -> String {
let key = match self {
Op::AddDeck => TR::UndoAddDeck,
Op::AddNote => TR::UndoAddNote,
Op::AnswerCard => TR::UndoAnswerCard,
Op::Bury => TR::StudyingBury,
Op::RemoveDeck => TR::DecksDeleteDeck,
Op::RemoveNote => TR::StudyingDeleteNote,
Op::RenameDeck => TR::ActionsRenameDeck,
Op::ScheduleAsNew => TR::UndoForgetCard,
Op::SetDueDate => TR::ActionsSetDueDate,
Op::Suspend => TR::StudyingSuspend,
Op::UnburyUnsuspend => TR::UndoUnburyUnsuspend,
Op::UpdateCard => TR::UndoUpdateCard,
Op::UpdateDeck => TR::UndoUpdateDeck,
Op::UpdateNote => TR::UndoUpdateNote,
Op::UpdatePreferences => TR::PreferencesPreferences,
Op::UpdateTag => TR::UndoUpdateTag,
Op::SetDeck => TR::BrowsingChangeDeck,
Op::SetFlag => TR::UndoSetFlag,
Op::FindAndReplace => TR::BrowsingFindAndReplace,
Op::ClearUnusedTags => TR::BrowsingClearUnusedTags,
Op::SortCards => TR::BrowsingReschedule,
Op::RenameTag => TR::ActionsRenameTag,
Op::RemoveTag => TR::ActionsRemoveTag,
Op::ReparentTag => TR::ActionsRenameTag,
Op::ReparentDeck => TR::ActionsRenameDeck,
Op::BuildFilteredDeck => TR::UndoBuildFilteredDeck,
Op::RebuildFilteredDeck => TR::UndoBuildFilteredDeck,
Op::EmptyFilteredDeck => TR::StudyingEmpty,
};
i18n.tr(key).to_string()
match self {
Op::AddDeck => i18n.undo_add_deck(),
Op::AddNote => i18n.undo_add_note(),
Op::AnswerCard => i18n.undo_answer_card(),
Op::Bury => i18n.studying_bury(),
Op::RemoveDeck => i18n.decks_delete_deck(),
Op::RemoveNote => i18n.studying_delete_note(),
Op::RenameDeck => i18n.actions_rename_deck(),
Op::ScheduleAsNew => i18n.undo_forget_card(),
Op::SetDueDate => i18n.actions_set_due_date(),
Op::Suspend => i18n.studying_suspend(),
Op::UnburyUnsuspend => i18n.undo_unbury_unsuspend(),
Op::UpdateCard => i18n.undo_update_card(),
Op::UpdateDeck => i18n.undo_update_deck(),
Op::UpdateNote => i18n.undo_update_note(),
Op::UpdatePreferences => i18n.preferences_preferences(),
Op::UpdateTag => i18n.undo_update_tag(),
Op::SetDeck => i18n.browsing_change_deck(),
Op::SetFlag => i18n.undo_set_flag(),
Op::FindAndReplace => i18n.browsing_find_and_replace(),
Op::ClearUnusedTags => i18n.browsing_clear_unused_tags(),
Op::SortCards => i18n.browsing_reschedule(),
Op::RenameTag => i18n.actions_rename_tag(),
Op::RemoveTag => i18n.actions_remove_tag(),
Op::ReparentTag => i18n.actions_rename_tag(),
Op::ReparentDeck => i18n.actions_rename_deck(),
Op::BuildFilteredDeck => i18n.undo_build_filtered_deck(),
Op::RebuildFilteredDeck => i18n.undo_build_filtered_deck(),
Op::EmptyFilteredDeck => i18n.studying_empty(),
}
.into()
}
}

View File

@ -1,21 +1,21 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use crate::i18n::{tr_args, I18n, TR};
use crate::i18n::I18n;
/// Short string like '4d' to place above answer buttons.
pub fn answer_button_time(seconds: f32, i18n: &I18n) -> String {
let span = Timespan::from_secs(seconds).natural_span();
let args = tr_args!["amount" => span.as_rounded_unit_for_answer_buttons()];
let key = match span.unit() {
TimespanUnit::Seconds => TR::SchedulingAnswerButtonTimeSeconds,
TimespanUnit::Minutes => TR::SchedulingAnswerButtonTimeMinutes,
TimespanUnit::Hours => TR::SchedulingAnswerButtonTimeHours,
TimespanUnit::Days => TR::SchedulingAnswerButtonTimeDays,
TimespanUnit::Months => TR::SchedulingAnswerButtonTimeMonths,
TimespanUnit::Years => TR::SchedulingAnswerButtonTimeYears,
};
i18n.trn(key, args)
let amount = span.as_rounded_unit_for_answer_buttons();
match span.unit() {
TimespanUnit::Seconds => i18n.scheduling_answer_button_time_seconds(amount),
TimespanUnit::Minutes => i18n.scheduling_answer_button_time_minutes(amount),
TimespanUnit::Hours => i18n.scheduling_answer_button_time_hours(amount),
TimespanUnit::Days => i18n.scheduling_answer_button_time_days(amount),
TimespanUnit::Months => i18n.scheduling_answer_button_time_months(amount),
TimespanUnit::Years => i18n.scheduling_answer_button_time_years(amount),
}
.into()
}
/// Short string like '4d' to place above answer buttons.
@ -42,16 +42,15 @@ pub fn time_span(seconds: f32, i18n: &I18n, precise: bool) -> String {
} else {
span.as_rounded_unit()
};
let args = tr_args!["amount" => amount];
let key = match span.unit() {
TimespanUnit::Seconds => TR::SchedulingTimeSpanSeconds,
TimespanUnit::Minutes => TR::SchedulingTimeSpanMinutes,
TimespanUnit::Hours => TR::SchedulingTimeSpanHours,
TimespanUnit::Days => TR::SchedulingTimeSpanDays,
TimespanUnit::Months => TR::SchedulingTimeSpanMonths,
TimespanUnit::Years => TR::SchedulingTimeSpanYears,
};
i18n.trn(key, args)
match span.unit() {
TimespanUnit::Seconds => i18n.scheduling_time_span_seconds(amount),
TimespanUnit::Minutes => i18n.scheduling_time_span_minutes(amount),
TimespanUnit::Hours => i18n.scheduling_time_span_hours(amount),
TimespanUnit::Days => i18n.scheduling_time_span_days(amount),
TimespanUnit::Months => i18n.scheduling_time_span_months(amount),
TimespanUnit::Years => i18n.scheduling_time_span_years(amount),
}
.into()
}
const SECOND: f32 = 1.0;

View File

@ -7,14 +7,13 @@ pub fn studied_today(cards: u32, secs: f32, i18n: &I18n) -> String {
let span = Timespan::from_secs(secs).natural_span();
let amount = span.as_unit();
let unit = span.unit().as_str();
let secs_per = if cards > 0 {
let secs_per_card = if cards > 0 {
secs / (cards as f32)
} else {
0.0
};
let args = tr_args!["amount" => amount, "unit" => unit,
"cards" => cards, "secs-per-card" => secs_per];
i18n.trn(TR::StatisticsStudiedToday, args)
i18n.statistics_studied_today(unit, secs_per_card, amount, cards)
.into()
}
impl Collection {

View File

@ -2,7 +2,7 @@
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use crate::err::{AnkiError, Result, TemplateError};
use crate::i18n::{tr_strs, I18n, TR};
use crate::i18n::I18n;
use crate::{cloze::add_cloze_numbers_in_string, template_filters::apply_filters};
use lazy_static::lazy_static;
use nom::branch::alt;
@ -247,11 +247,11 @@ fn parse_inner<'a, I: Iterator<Item = TemplateResult<Token<'a>>>>(
}
fn template_error_to_anki_error(err: TemplateError, q_side: bool, i18n: &I18n) -> AnkiError {
let header = i18n.tr(if q_side {
TR::CardTemplateRenderingFrontSideProblem
let header = if q_side {
i18n.card_template_rendering_front_side_problem()
} else {
TR::CardTemplateRenderingBackSideProblem
});
i18n.card_template_rendering_back_side_problem()
};
let details = localized_template_error(i18n, err);
let more_info = i18n.card_template_rendering_more_info();
let info = format!(
@ -273,31 +273,22 @@ fn localized_template_error(i18n: &I18n, err: TemplateError) -> String {
TemplateError::ConditionalNotOpen {
closed,
currently_open,
} => {
if let Some(open) = currently_open {
i18n.trn(
TR::CardTemplateRenderingWrongConditionalClosed,
tr_strs!(
"found"=>format!("{{{{/{}}}}}", closed),
"expected"=>format!("{{{{/{}}}}}", open)),
)
} else {
i18n.trn(
TR::CardTemplateRenderingConditionalNotOpen,
tr_strs!(
"found"=>format!("{{{{/{}}}}}", closed),
"missing1"=>format!("{{{{#{}}}}}", closed),
"missing2"=>format!("{{{{^{}}}}}", closed)
),
)
}
} => if let Some(open) = currently_open {
i18n.card_template_rendering_wrong_conditional_closed(
format!("{{{{/{}}}}}", closed),
format!("{{{{/{}}}}}", open),
)
} else {
i18n.card_template_rendering_conditional_not_open(
format!("{{{{/{}}}}}", closed),
format!("{{{{#{}}}}}", closed),
format!("{{{{^{}}}}}", closed),
)
}
TemplateError::FieldNotFound { field, filters } => i18n.trn(
TR::CardTemplateRenderingNoSuchField,
tr_strs!(
"found"=>format!("{{{{{}{}}}}}", filters, field),
"field"=>field),
),
.into(),
TemplateError::FieldNotFound { field, filters } => i18n
.card_template_rendering_no_such_field(format!("{{{{{}{}}}}}", filters, field), field)
.into(),
}
}