i18n: per-network locale (en/es/fr) for karma replies and the web board
All checks were successful
ci / check (push) Successful in 45s
All checks were successful
ci / check (push) Successful in 45s
This commit is contained in:
parent
f290554325
commit
739fc8ad94
11 changed files with 406 additions and 115 deletions
|
|
@ -1,5 +1,6 @@
|
|||
use rustbot::bot::module::{Action, Chat, Command, Module};
|
||||
use rustbot::bot::modules::karma::{extract_reason, format_event, parse_changes, Karma};
|
||||
use rustbot::i18n::Locale;
|
||||
|
||||
fn chat<'a>(sender: &'a str, text: &'a str) -> Chat<'a> {
|
||||
Chat {
|
||||
|
|
@ -208,3 +209,53 @@ fn on_message_appends_to_the_event_log() {
|
|||
let _ = std::fs::remove_file(&path);
|
||||
let _ = std::fs::remove_file(&log);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spanish_reason_connector_is_stripped() {
|
||||
assert_eq!(
|
||||
extract_reason("rust++ porque es rápido").as_deref(),
|
||||
Some("es rápido")
|
||||
);
|
||||
assert_eq!(
|
||||
extract_reason("rust++ por los tests").as_deref(),
|
||||
Some("los tests")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn replies_in_spanish_for_es_locale() {
|
||||
let path = std::env::temp_dir().join("rubot-test-karma-es.json");
|
||||
let log = std::env::temp_dir().join("rubot-test-karma-es.events.jsonl");
|
||||
let _ = std::fs::remove_file(&path);
|
||||
let _ = std::fs::remove_file(&log);
|
||||
let mut k = Karma::with_path_locale(path.clone(), Locale::Es);
|
||||
k.on_message(&chat("alice", "rust++ porque es bueno"));
|
||||
// report
|
||||
let cmd = Command {
|
||||
sender: "z",
|
||||
reply_to: "#argentina",
|
||||
name: "karma",
|
||||
args: &["rust"],
|
||||
prefix: ">",
|
||||
network: "libera",
|
||||
};
|
||||
let r = match k.on_command(&cmd).as_slice() {
|
||||
[Action::Reply(s)] => visible(s),
|
||||
_ => panic!("expected one reply"),
|
||||
};
|
||||
assert!(r.contains("tiene 1 de karma"), "{r}");
|
||||
assert!(r.contains("(#1 de 1)"), "{r}");
|
||||
assert!(r.contains("último: \"es bueno\""), "{r}");
|
||||
// unseen thing
|
||||
let cmd2 = Command {
|
||||
args: &["ghost"],
|
||||
..cmd
|
||||
};
|
||||
let ghost = match k.on_command(&cmd2).as_slice() {
|
||||
[Action::Reply(s)] => visible(s),
|
||||
_ => panic!("expected one reply"),
|
||||
};
|
||||
assert!(ghost.contains("todavía no hay karma para"), "{ghost}");
|
||||
let _ = std::fs::remove_file(&path);
|
||||
let _ = std::fs::remove_file(&log);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use rustbot::i18n::Locale;
|
||||
use rustbot::karma_web::{parse_board, parse_events, render};
|
||||
|
||||
fn board_with_events(net: &str, store: &str, log: &str) -> rustbot::karma_web::Board {
|
||||
|
|
@ -51,11 +52,8 @@ fn renders_hero_podium_and_scores() {
|
|||
"libera",
|
||||
r#"{"rust":{"n":5,"why":"clean PR","by":"alice"}}"#,
|
||||
);
|
||||
let html = render(&[b], 0);
|
||||
assert!(
|
||||
html.contains(">karma<"),
|
||||
"wordmark missing: has no karma mark"
|
||||
);
|
||||
let html = render(&[b], 0, Locale::En);
|
||||
assert!(html.contains(">karma<"), "wordmark missing");
|
||||
assert!(html.contains("podium"), "no podium");
|
||||
assert!(html.contains(">rust<"), "champion nick missing");
|
||||
assert!(html.contains(">+5<"), "score missing");
|
||||
|
|
@ -67,34 +65,42 @@ fn renders_activity_and_givers_from_events() {
|
|||
let log = "{\"t\":100,\"o\":\"rust\",\"d\":1,\"by\":\"alice\",\"why\":\"clean PR\"}\n\
|
||||
{\"t\":200,\"o\":\"docs\",\"d\":1,\"by\":\"alice\"}\n";
|
||||
let b = board_with_events("libera", r#"{"rust":1,"docs":1}"#, log);
|
||||
let html = render(&[b], 0);
|
||||
let html = render(&[b], 0, Locale::En);
|
||||
assert!(html.contains("recent activity"), "no activity section");
|
||||
assert!(html.contains("top givers"), "no givers section");
|
||||
assert!(html.contains("gave"), "no feed verb");
|
||||
// alice made two gifts -> shown in givers panel
|
||||
assert!(
|
||||
html.contains("2 gifts"),
|
||||
"giver count wrong: {}",
|
||||
html.contains("gift")
|
||||
);
|
||||
assert!(
|
||||
html.contains("data-t=\"200\""),
|
||||
"feed sorted/newest-first missing"
|
||||
);
|
||||
assert!(html.contains("2 gifts"), "giver count wrong");
|
||||
assert!(html.contains("data-t=\"200\""), "feed newest-first missing");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_states_are_friendly() {
|
||||
// no karma at all
|
||||
let html = render(&[], 0);
|
||||
let html = render(&[], 0, Locale::En);
|
||||
assert!(html.contains("No karma yet"), "{html}");
|
||||
// karma but no event history yet
|
||||
let b = parse_board("libera", r#"{"romaka":2}"#);
|
||||
let html = render(&[b], 0);
|
||||
let html = render(&[b], 0, Locale::En);
|
||||
assert!(html.contains("Nothing yet"), "empty activity state missing");
|
||||
assert!(html.contains("Be the first"), "empty givers state missing");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn renders_spanish_chrome() {
|
||||
let log = "{\"t\":100,\"o\":\"rust\",\"d\":1,\"by\":\"nadia\",\"why\":\"buen PR\"}\n";
|
||||
let b = board_with_events("libera", r#"{"rust":1}"#, log);
|
||||
let html = render(&[b], 0, Locale::Es);
|
||||
assert!(html.contains("karma neto"), "es stat label missing");
|
||||
assert!(
|
||||
html.contains("actividad reciente"),
|
||||
"es activity heading missing"
|
||||
);
|
||||
assert!(html.contains("top donantes"), "es givers heading missing");
|
||||
assert!(html.contains("le dio a"), "es feed verb missing");
|
||||
// relative-time config for the client is Spanish
|
||||
assert!(html.contains("\"pre\":\"hace \""), "es time config missing");
|
||||
// user content is never translated
|
||||
assert!(html.contains("buen PR") && html.contains(">rust<"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn escapes_untrusted_irc_input_everywhere() {
|
||||
let log = "{\"t\":1,\"o\":\"<script>\",\"d\":1,\"by\":\"a&b\",\"why\":\"\\\"><img src=x>\"}\n";
|
||||
|
|
@ -103,7 +109,7 @@ fn escapes_untrusted_irc_input_everywhere() {
|
|||
r#"{"<script>":{"n":1,"why":"\"><img src=x>","by":"a&b"}}"#,
|
||||
log,
|
||||
);
|
||||
let html = render(&[b], 0);
|
||||
let html = render(&[b], 0, Locale::En);
|
||||
assert!(!html.contains("<img"), "raw img tag leaked");
|
||||
assert!(html.contains("<script>"), "nick not escaped");
|
||||
assert!(html.contains("a&b"), "giver not escaped");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue