feat: add sticky error-aware key mastery
Persist ranked-only mastery and use it consistently across progression, milestones, counts, and localized UI. Preserve mastery during history rebuilds, replay errors accurately, and generate replay-derived test profiles. Document the follow-up plan to remove the drill history cap.
This commit is contained in:
+15
-9
@@ -2,8 +2,8 @@ pub use rust_i18n::t;
|
||||
|
||||
/// Available UI locale codes. Separate from dictionary language support.
|
||||
pub const SUPPORTED_UI_LOCALES: &[&str] = &[
|
||||
"en", "de", "es", "fr", "it", "pt", "nl", "sv", "da", "nb", "fi", "pl", "cs", "ro", "hr",
|
||||
"hu", "lt", "lv", "sl", "et", "tr",
|
||||
"en", "de", "es", "fr", "it", "pt", "nl", "sv", "da", "nb", "fi", "pl", "cs", "ro", "hr", "hu",
|
||||
"lt", "lv", "sl", "et", "tr",
|
||||
];
|
||||
|
||||
pub fn set_ui_locale(locale: &str) {
|
||||
@@ -18,7 +18,11 @@ pub fn set_ui_locale(locale: &str) {
|
||||
/// Retrieve the set of all translation keys for a given locale.
|
||||
/// Used by the catalog parity test to verify every key exists in every locale.
|
||||
#[cfg(test)]
|
||||
fn collect_yaml_keys(value: &serde_yaml::Value, prefix: &str, keys: &mut std::collections::BTreeSet<String>) {
|
||||
fn collect_yaml_keys(
|
||||
value: &serde_yaml::Value,
|
||||
prefix: &str,
|
||||
keys: &mut std::collections::BTreeSet<String>,
|
||||
) {
|
||||
match value {
|
||||
serde_yaml::Value::Mapping(map) => {
|
||||
for (k, v) in map {
|
||||
@@ -54,9 +58,7 @@ pub fn localized_language_layout_error(
|
||||
layout = layout_key
|
||||
)
|
||||
.to_string(),
|
||||
LanguageBlockedBySupportLevel(key) => {
|
||||
t!("errors.language_blocked", key = key).to_string()
|
||||
}
|
||||
LanguageBlockedBySupportLevel(key) => t!("errors.language_blocked", key = key).to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,8 +69,8 @@ mod tests {
|
||||
|
||||
fn locale_keys(locale: &str) -> BTreeSet<String> {
|
||||
let path = format!("locales/{locale}.yml");
|
||||
let content = std::fs::read_to_string(&path)
|
||||
.unwrap_or_else(|e| panic!("Failed to read {path}: {e}"));
|
||||
let content =
|
||||
std::fs::read_to_string(&path).unwrap_or_else(|e| panic!("Failed to read {path}: {e}"));
|
||||
let root: serde_yaml::Value = serde_yaml::from_str(&content)
|
||||
.unwrap_or_else(|e| panic!("Failed to parse {path}: {e}"));
|
||||
let mut keys = BTreeSet::new();
|
||||
@@ -111,7 +113,11 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
assert!(errors.is_empty(), "Catalog parity errors:\n{}", errors.join("\n"));
|
||||
assert!(
|
||||
errors.is_empty(),
|
||||
"Catalog parity errors:\n{}",
|
||||
errors.join("\n")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user